今天继续复习贪心。
经过这几天的磨练,我终于明白,想要用好贪心,就要多做题,做的题目多了,套路就熟悉了。
这样就不至于一看题目,两眼一抹黑,想半天想不出思路来。
所以我们继续搞题。
下面是一道题。
加工木块,每个木块都有自己的质量和长度,如果一个加工的木块的长度和质量都比上一个大,那么不需要调机器,否则花一分钟调机器,机器在一开始启动需要一分钟。
求怎么加工使时间最少。
这个题目的思路是,首先按照质量或者长度排序,接着按顺序对另一个量比较,找出所有能按规矩排列的排列的数量,就是需要的时间。
上代码。
#include<cmath>
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
using namespace std;
struct box
{
int l; //长度
int w; //质量
bool u; //是否已被使用
};
int cmp(box x,box y) //排序规则
{
if(x.w==y.w)
{
return x.l<y.l;
}
else
{
return x.w<y.w;
}
}
int main()
{
int m;
scanf("%d",&m);
while(m--)
{
box a[10000];
int n,sum=0;
scanf("%d",&n);
for(int i=0;i<n;i++)
{
scanf("%d %d",&a[i].l,&a[i].w);
a[i].u=false;
}
sort(a,a+n,cmp);
for(int i=0;i<n;i++)
{
if(a[i].u) //如果被使用过了,那么跳过
{
continue;
}
int maxx=a[i].l; //存最大值
for(int j=i+1;j<n;j++)
{
if(!a[j].u&&maxx<=a[j].l) //没有被使用,且长度比后面小
{
a[j].u=true;
maxx=a[j].l; //最大值更换
}
}
sum++; //时间累加
}
cout<<sum<<endl;
}
return 0;
}
还有另一道
有m个人每个人有n张牌,牌的大小从1到n*m;知道自己的n张牌的大小。
至少可以赢几次?
这个题的思路是,先把自己的牌从大到小排序,然后挑出对方最大的牌,用自己的牌挨个与之比较。
如果自己的大,自己赢一次,如果自己的小,找到下一个大的牌继续比较。
下面是代码
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
bool cmp(int a,int b)
{
return a>b;
}
int main()
{
int m,n;,k=1;
int s[60]; //保存自己的牌的
int pa[1000]; //全部牌
while(scanf("%d%d",&m,&n))
{
if(m==0&&n==0)
return 0;
int i;
memset(pa,0,sizeof(pa));
for(i=0; i<n; i++)
{
scanf("%d",&s[i]);
pa[s[i]]=1; //标记自己的牌
}
sort(s,s+n,cmp);
int a=n*m,sum=0;
while(pa[a]) //找出除了自己的牌的最大的牌
a--;
for(i=0;i<n;i++)
{
if(s[i]>a) //自己的牌大,赢一局
sum++;
else
{
pa[a]=1; //标记这张牌无人能敌
while(pa[a]) 找出第二大的牌
a--;
}
}
cout<<"Case "<<k<<": "<<sum;
k++;
}
return 0;
}
总之,多做题,多总结,就对了。