在于递归和递推做了几个晚上的斗争之后;
荀彧同学来到了贪心算法;
讲真,有时候题目看懂了;
但是!
一点思路都没有;
内心绝望;
在各位大佬的帮助下;
荀彧同学算是稍微学会了一点吧;
在这里做个小结;
1>修理牛棚
上题目:
在一个暴风雨的夜晚,农民约翰的牛棚的屋顶、门被吹飞了。 好在许多牛正在度假,所以牛棚没有住满。 有些牛棚里有牛,有些没有。 所有的牛棚有相同的宽度。 自顶遗失以后,农民约翰必须尽快在牛棚之上竖立起新的木板。 他的新木材供应者将会供应他任何他想要的长度,但是供应者只能提供有限数目的木板。 农民约翰想将他购买的木板总长度减到最少。 给出 M(1<= M<=50),可能买到的木板最大的数目;S(1<= S<=200),牛棚的总数;C(1 <= C <=S) 牛棚里牛的数目,和牛所在的牛棚的编号stall_number(1 <= stall_number <= S),计算拦住所有有牛的牛棚所需木板的最小总长度。 输出所需木板的最小总长度作为的答案。
第 1 行: M , S 和 C(用空格分开) 第 2 到 C+1行: 每行包含一个整数,表示牛所占的牛棚的编号。
单独的一行包含一个整数表示所需木板的最小总长度。
input
4 50 18
3
4
6
8
14
15
16
17
21
25
26
27
30
31
40
41
42
43
output
25
时间限制:1s
空间限制:256MB
[ 一种最优的安排是用板拦住牛棚3-8,14-21,25-31,40-43.]
这道题卡了三天还是一点思路都没有;
于是鼓起胆子去问章晟大佬;
得到这样的思路:
假设你把所有牛棚用一块板子盖起来要用多少长的木板?(以样例数据为例)
43-3+1=41对吧(因为是闭区间,两边都要盖起来,所以+1);
然后你再把两个相邻数据之间的距离算出来,排个序;
用个循环把大的间隔剪掉;
这就是剩下的最小的木板长度;
不得不说;
思路是真的奇特;
不再荀彧同学这种文科生的理解范围之内;
上代码:
#include
using namespace std;
int main()
{
int m,s,c,sum=0;
int a[222],b[111];
cin>>m>>s>>c;
for(int i=1;i<=c;i++)
cin>>a[i];
sort(a+1,a+c+1);
sum=a[c]-a[1]+1;
if(m>=c)
{
cout<<c<<endl;
return 0;
}
for(int i=2;i<=c;i++)
b[i-1]=a[i]-a[i-1]-1;
sort(b+1,b+c);
for(int i=c-1;i>c-m;i--)
sum-=b[i];
cout<<sum<<endl;
return 0;
}
从此发现,贪心是一个要用非正常人思路去理解的;
内心绝望;
心情简单;
end...
2>巧克力
上题目:
有一块n××m的矩形巧克力,准备将它切成n××m块。巧克力上共有n-1条横线和m-1条竖线,你每次可以沿着其中的一条横线或竖线将巧克力切开,无论切割的长短,沿着每条横线切一次的代价依次为y1,y2,…,yn-1,而沿竖线切割的代价依次为x1,x2,…,xm-1。例如,对于下图6××4的巧克力,
我们先沿着三条横线切割,需要3刀,得到4条巧克力,然后再将这4条巧克力沿竖线切割,每条都需要5刀,则最终所花费的代价为y1+y2+y3+4*(x1+x2+x3+x4+x5)。 当然,上述简单切法不见得是最优切法,那么怎样切割该块巧克力,花费的代价最少呢?
第一行为两个整数n和m。 接下来n-1行,每行一个整数,分别代表x1,x2,…,xn-1。 接下来m-1行,每行一个整数,分别代表y1,y2,…,ym-1。
输出一整数,为切割巧克力的最小代价。
input
6 4
2
1
3
1
4
4
1
2
output
42
时间限制:1s1s
空间限制:256MB256MB
30%的数据,n<=100,m<=100 100%的数据,n<=10000,m<=10000
一刀一刀切下去的都是代价啊;
不能直接咬么;
这是一道很水得体;
正常人都能想得到;
要从代价大的开始切;
所以给两个数组排个序;
先切代价大的嘛;
然后再定义横着的块数和竖着的块数(定义时都是等于1,因为本来就有一块在那里嘛);
这个很简单,开个循环就好了;
直接放代码:
#include
using namespace std;
int n,m,sum=0;
int a[10100],b[10100];
int k1=1,k2=1;
inline bool cmp(int a,int b)
{
return a>b;
}
void init()
{
cin>>n>>m;
for(int i=1;i<=n-1;i++)
cin>>a[i];
for(int i=1;i<=m-1;i++)
cin>>b[i];
}
void work()
{
sort(a+1,a+n,cmp);
sort(b+1,b+m,cmp);
for(int i=1;i<=m+n-2;i++)
if(a[k1]>b[k2])
sum+=a[k1]*k2,k1++;
else sum+=b[k2]*k1,k2++;
cout<<sum<<endl;
}
int main()
{
init();
work();
return 0;
}
当时敲代码的时候脑子不清楚;
k1和k2的顺序neng反了;
所以说还是要仔细啊;
end...
先放着这两道题吧;
贪心估计还可以做两天;
下次争取做个更有水平的总结;
全文终。