Barn Repair
Description
在一个夜黑风高、下着暴风雨的夜晚,farmer John的牛棚的屋顶、门都被吹飞了。所幸,许多牛都在度假,所以牛棚并没有住满。
牛棚一个挨着一个相邻排列成一行,牛就在里面过夜。一些牛棚里面有牛,而一些没有。所有的牛棚都有相同的宽度。
自从门被吹走后,farmer John必须尽快地在牛棚前建立新的木板。他的新木料供应商将会供应给他任意他想要长度的木板,但是供应商只能够提供少量的木板。Farmer John想要将木板的总长度减到最少。
给出可能买到的木板的最大数目M(1<= M<=50),每块长度任意;牛棚的总数S(1<= S<=200); 牛棚里牛的总数C(1 <= C <=S);以及牛所在牛棚的编号stall_number(1 <= stall_number <= S),计算拦住所有有牛的牛棚所需木板的最小总长度。
输出你所计算得到的所需木板的最小总长度作为答案。
PROGRAM NAME: barn1
INPUT FORMAT
第 1 行: M,S和C(用空格分开)
第 2 到 C+1行: 每行包含一个整数,表示牛所占的牛棚的编号
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
单独的一行包含一个整数表示所需木板的最小总长度。
SAMPLE OUTPUT (file barn1.out)
25
Explannation
这道题最初其实没怎么看懂,后面分析25的得来才懂了,这里也解释一下是个什么意思。同时也可以分析出为什么洛谷上说这是一个吝啬的供应商:因为规定了只卖M块木板给John,所以说一般来说长度都会买多,自然长度一多供应商可以赚的钱也要多一些。下面解释一下25的得来,共有两种方案:
第一种:第一块3 – 8 ,第二块14 – 21,第三块25 – 31,第四块40 – 43,总长度25
第二种:第一块3 – 8 ,第二块14 – 17,第三块21 – 31,第四块40 – 43,总长度25
找不出比这两种方案总长度更短的方案,故结果就是25,那么基本上明白了,接下来就是设计算法了。
设计算法
这道题其实解法挺多的,基本上思路是:
如果M>=C,需要板子最小长度显然是C,这是毫无疑问的。对于M<C的情况,先将编号最小的牛和编号最大的牛之间包括自身一共有多少块板子计算出来,最多使用M块板子,肯定是全部用上才能够达到最小值的,这个很显然,那么M块板子全部用上,就会产生M-1个间隔,求出所有相邻两头牛之间的间隔,将总板子数减去最大的M-1个间隔,就得到了最小长度。
思路大致是这样,实现的方式有很多,下面用C++写了两种解法。
C++编写
解法一:
/*
ID: your_id_here
TASK: barn1
LANG: C++
*/
#include<iostream>
#include<algorithm>
using namespace std;
int M,S,C;
int stalls[201],gap[201];
void solve()
{
int len=stalls[C-1]-stalls[0]+1;
for(int i=0;i<C-1;++i)
gap[i]=stalls[i+1]-stalls[i]-1;
sort(gap,gap+C-1);
for(int i=C-2;i>C-M-1;--i)
len-=gap[i];
cout<<len<<endl;
}
int main()
{
freopen("barn1.in","r",stdin);
freopen("barn1.out","w",stdout);
cin>>M>>S>>C;
for(int i=0;i<C;++i)
cin>>stalls[i];
sort(stalls,stalls+C); //按照牛所占牛棚编号从小到大排序
if(M>=C)
cout<<C<<endl;
else
solve();
return 0;
}
解法二:
/*
ID: your_id_here
TASK: barn1
LANG: C++
*/
#include<iostream>
#include<algorithm>
using namespace std;
int M,S,C;
int stalls[201];
bool st[201];
void solve()
{
int len=stalls[C-1]-stalls[0]+1;
for(int i=0;i<M-1;++i) //一共使用M块板子,故有M-1个间隔
{
int temp=0;
int num=0;
for(int j=0;j<C-1;++j)
{
if(!st[j] && temp<stalls[j+1]-stalls[j]-1)
{
temp=stalls[j+1]-stalls[j]-1;
num=j;
}
}
st[num]=true;
len-=temp;
}
cout<<len<<endl;
}
int main()
{
freopen("barn1.in","r",stdin);
freopen("barn1.out","w",stdout);
cin>>M>>S>>C;
for(int i=0;i<C;++i)
{
cin>>stalls[i];
st[i]=false;
}
sort(stalls,stalls+C); //按照牛所占牛棚编号从小到大排序
if(M>=C)
cout<<C<<endl;
else
solve();
return 0;
}