USACO 1.4 Barn Repair 题解&解题报告

这篇博客详细介绍了USACO比赛中Barn Repair问题的解题思路,包括四种不同的解决方案:贪心算法、正向思维、动态规划和优化间隙策略。每种方法都阐述了其原理,并提供了相应的算法优化点。博客还包含问题的输入输出格式和样例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

It was a dark and stormy night that ripped the roof and gates off the stalls that hold Farmer John's cows. Happily, many of the cows were on vacation, so the barn was not completely full.

The cows spend the night in stalls that are arranged adjacent to each other in a long line. Some stalls have cows in them; some do not. All stalls are the same width.

Farmer John must quickly erect new boards in front of the stalls, since the doors were lost. His new lumber supplier will supply him boards of any length he wishes, but the supplier can only deliver a small number of total boards. Farmer John wishes to minimize the total length of the boards he must purchase.

Given M (1 <= M <= 50), the maximum number of boards that can be purchased; S (1 <= S <= 200), the total number of stalls; C (1 <= C <= S) the number of cows in the stalls, and the C occupied stall numbers (1 <= stall_number <= S), calculate the minimum number of stalls that must be blocked in order to block all the stalls that have cows in them.

Print your answer as the total number of stalls blocked.

在一个暴风雨的夜晚,农民约翰的牛棚的屋顶、门被吹飞了. 好在许多牛正在度假,所以牛棚没有住满. 剩下的牛一个紧挨着另一个被排成一行来过夜. 有些牛棚里有牛,有些没有. 所有的牛棚有相同的宽度. 自门遗失以后,农民约翰很快在牛棚之前竖立起新的木板. 他的新木材供应者将会供应他任何他想要的长度,但是供应者只能提供有限数目的木板. 农民约翰想将他购买的木板总长度减 到少. 给出 M(1<= M<=50),可能买到的木板大的数目;S(1<= S<=200),牛棚的总数;C(1 <= C <=S) 牛棚里牛的数目,和牛所在的牛棚的编号 stall_number(1 <= stall_number <= S),计算拦住 所有有牛的牛棚所需木板的小总长度. 输出所需木板的小总长度作为的答案.

PROGRAM NAME: barn1

INPUT FORMAT

Line 1:M, S, and C (space separated)
Lines 2-C+1:Each line contains one integer, the number of an occupied stall.

SAMPLE INPUT (file barn1.in)

4 50 18
3
4
6
8
14
15
16
17
21
25
26
27
30
31
40
41
42
43

OUTPUT FORMAT

A single line with one integer that represents the total number of stalls blocked.

SAMPLE OUTPUT (file barn1.out)

25

题解:

思路一 

要使木板总长度最少,就要使未盖木板的长度最大。我们先用一块木板盖住牛棚,然后,每次从盖住的范围内选一个最大的空隙,以空隙为 界将木板分成两块,重复直到分成 m 块或没有空隙。可以用二叉堆来优化算法。贪心的证明略。

思路二 

显然,当所有木板均用上时,长度最短。正向思维,初始状态有 c 块木板, 每块木板只盖住一个牛棚。由c块倒推至 m 块木板,每次寻找这样的两个牛棚:其间距在所有未连接的木板中最小。当这两个牛棚的木板连接时,总木板数减 1,总长度增加 1。 

思路三 

还可以用动态规划求解,将有牛的牛棚排序后,设置一个函数 d[i,j]表示第 i 个牛修到 第 j 个牛需要使用的木版长度,设 f[i,j]表示用前 i 个木版修到第 j 头牛所用的最短长度。 f[i,j]=f[i-1,k-1]+d[k,j] (i<=k<=j) 思路四 显然,当所有木板均用上时,长度最短。用上 m 块木板时有 m-1 各间隙。现在的目标 是让总间隙最大。将相邻两个有牛的牛棚之间间隔的牛棚数排序,选取最大的 m-1 个作为 间隙,其余地方用木板盖住即可。


代码如下:

/*
ID: zhaoxia13
LANG: C
TASK: barn1
*/

#include <stdio.h>
#include <stdlib.h>

int temp, stall[205] = {0}, store[205] = {0}, t = 0;

void bi(int a[], int l, int r)
{
	int i, j, mid;
	i = l; j = r;
	mid = a[(i+j) / 2];
	while(i <= j)
	{
		while(i <= j && a[i] > mid)
			i++;
		while(i <= j && a[j] < mid)
			j--;
		if(i <= j)
		{
			temp = a[i]; a[i] = a[j]; a[j] = temp;
			i++; j--;
		}
	}

	if(i < r) bi(a, i, r);
	if(j > l) bi(a, l, j);
}

int main()
{
	freopen("barn1.in", "r", stdin);
	freopen("barn1.out", "w", stdout);
	int m, s, c, min = 99999, max = -10;
	int i, j, b, sum = 0, flag = 0;
	scanf("%d%d%d", &m, &s, &c);

	for(i = 1; i <= c; i++)
	{
		scanf("%d", &b);
		stall[b] = 1;
		if(b < min) min = b;
		if(b > max) max = b;
	}

	for(i = min; i <= max;)
	{
		j = i;
		if(!flag)
		{
			while(i <= max && stall[i] == 1) i++;
			flag = 1;
		}
		else
		{
			while(i <= max && stall[i] == 0) i++;
			flag = 0;
			if(i <= max)
				store[t++] = i - j;
		}
	}


	bi(store, 0, t);
	for(i = m-1; i >= 0 && i <= t; i++)
		sum += store[i];

	printf("%d\n", sum+c);
	fclose(stdin);
	fclose(stdout);
	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值