USCAO 1.3.2 Barn Repair 修理牛棚





描述

在一个夜黑风高,下着暴风雨的夜晚,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:

(file barn1.in)

  • 第 1 行: 木板最大的数目M ,牛棚的总数S 和 牛的总数C(用空格分开)
  • 第 2 到 C+1行: 每行包含一个整数,表示牛所占的牛棚的编号。

OUTPUT FORMAT:

(file barn1.out)

单独的一行包含一个整数表示所需木板的最小总长度。

[编辑]SAMPLE INPUT

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

[编辑]SAMPLE OUTPUT

25

[ 一种最优的安排是用板拦牛棚3-8,14-21,25-31,40-43.]



解题思路:

这道题的解题思路同样有很多。关键他分布在贪心的这一章节,所以,我们就姑且使用贪心来做了,问题求的是最小的木板长度来把目前棚子中有牛

的地方封住,那么我们首先想到了贪心(PS:怎么贪心呢?)其实,只需要找到第一头牛和最后一头牛,然后让sum=end-start-1;也就是说,找到了第一个

和最后一个牛的位置,那么这就是一条由长长的大木板所覆盖的牛棚了,接下来,因为题目要求只是用M个木板,那么M个数量就决定了我们贪心的策略,

也就是说,这个关键的决策量对于其分布起了很大的作用,不难发现,M个木板中间必定存在M-1个空隙,然后,就是求出前M-1大的空隙,不断的更新

sum,这样,就可以得到我们最小的木板长度了。。。

QAQ,通过这道题的学习,还让我学会了greater<int>()这个内置比较函数的使用方法,

比如这样来说,greater<int>()存在 # include<functional>的头文件中,那么在以后处理从大到小的排序的问题,我们可以直接这样写:

sort( a,a+n,greater<int>());

附上一段代码来说明他的功能了。。。

#include<iostream>
#include<algorithm>//因为用了sort()函数

#include<functional>//因为用了greater<int>()
using namespace std;

void main()
{
 int a[]={3,1,4,2,5};
 int len=sizeof(a)/sizeof(int);//这里切记要除以sizeof(int)!
 sort(a,a+len,greater<int>());//内置类型的由大到小排序
 for(int i=0;i<len;i++)
  cout<<a[i]<<" ";
}





代码:

/*
ID: wikioi_2
PROG: barn1
LANG: C++
*/

# include<cstdio>
# include<iostream>
# include<algorithm>
# include<cstring>
# include<functional>

using namespace std;

# define MAX 200

int a[MAX];//用来模拟整个牛棚
int b[MAX];//用来存放间隙的长度

int cmp ( int x,int y )
    {
        return x>y;
    }

int main(void)
{
    freopen("barn1.in","r",stdin);
	freopen("barn1.out","w",stdout);
    memset(a,0,sizeof(a));
    memset(b,0,sizeof(b));
    int M,S,C;
    cin>>M>>S>>C;
    for ( int i = 0;i < C;i++ )
        {
            cin>>a[i];
        }
        sort(a,a+C);//默认从小到大进行排序
        int sum = a[C-1] - a[0] + 1;
        for ( int j = 1;j < C;j++ )
            {
                b[j] = a[j] - a[j-1] - 1;
            }

            sort(b+1,b+C,greater<int>());//默认从大到小进行排序
        for ( int i = 1;i < M;i++ )
            {
                sum-=b[i];
            }
            cout<<sum<<endl;

    return 0;

}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值