前言
贪心贪心,顾名思义,就是说你要很贪
(当然你可能会被抓)
不同于 动态规划 的目光长远,贪心 往往“鼠目寸光”,只注重眼前的利益
而这也是贪心的定义:
在当前情况下寻找 局部 最优解
所以当你确定一道题目是贪心时,不要想太多,每次取最优即可
纵使后面可能会有更好的情况,那也不关咱们的事
(谁让咱们贪呢)
当然有一些贪心题看起来很像dp,千万别搞混(比如例题第一题)
例题
Luogu P2095 营养膳食
注意:这题不是dp,这题不是dp,这题不是dp!
(我还信誓旦旦地说这是背包来着)
第一遍看我就只想到了 dp ,写了 10min 之后发现 dp 完全无法实现
所以这题是贪心无疑
那么我们怎么贪呢?
大家应该还记得贪心的定义,所以我们每次只要吃脂肪尽可能多的就可以了
做法:
1. 读入每种食物最多吃多少份
2. 读入食物的脂肪和种类
3. 按脂肪排序(核心部分 非常重要)
4. 排序部分我们从大到小排,所以从第一份开始判断(i from 1 to m)
5. 先判断还能不能吃这一种
6. 再判断有没有越界(
now≤n
)
7. 符合条件直接加上即可
写完之后我们会发现,得出的就是最优解,因为脂肪最多的那些都被我们吃掉了
代码仅供参考:
#include<cstdio>
#include<algorithm>//使用sort函数
using namespace std;
int n,m,k,Max_Eat[105],ans;
struct node//创建结构体存信息
{
int Fat,Type;//脂肪和种类
}a[205];
bool cmp(node x,node y)//sort的判断用函数
{
return x.Fat>y.Fat;//从大到小排
}
int main()
{
scanf("%d %d %d",&n,&m,&k);
for(int i=1;i<=k;i++) scanf("%d",&Max_Eat[i]);
for(int i=1;i<=n;i++) scanf("%d%d",&a[i].Fat,&a[i].Type);//读入数据
sort(a+1,a+n+1,cmp);//核心的排序部分
int tot=1;//tot代表现在吃到了第几份
for(int i=1;i<=m;i++)//最多吃m份
{
if(Max_Eat[a[tot].Type]>0 && tot<=n)//如果符合条件
{
ans+=a[tot].Fat;//直接加上
Max_Eat[a[tot].Type]--;//这一步也很重要,当前种类能吃的份数-1
tot++;//到下一份
}
else tot++;//如果不能吃也到下一份
}
printf("%d",ans);//输出即可
return 0;
}
再来一道:
Luogu P2695 骑士的工作
这道题目是一题比较明显的贪心,我们需要让每个骑士砍掉他所能砍的最小的头
那么有人就要问了:这怎么实现呢?
排序呗!
(实际上大多贪心的题目都要用到排序,sort是一个必须要学的东西)
做法:
1. 读入每个骑士能砍的头的大小
2. 读入龙头的大小
3. 分别排序(核心代码 从小到大排)
4. 对每个骑士进行判断,让他砍掉他所能砍的最小的头
5. 如果能砍
ans+k[i]
,同时
sum+1
6. 如果
sum<n
输出 you died! , 否则输出
ans
当然我们可以进行一些小小的优化
注意:每个骑士只能砍一个龙头
代码仅供参考:
#include<cstdio>
#include<algorithm>//sort大法好
using namespace std;
int n,m,d[20005],k[20005],ans,sum;
bool used[20005];
int main()
{
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++) scanf("%d",&d[i]);
for(int i=1;i<=m;i++) scanf("%d",&k[i]);//读入数据
if(n>m)//小优化,如果骑士比恶龙少直接就可以放弃治疗【划掉】退出程序了
{
printf("you died!");
return 0;
}
sort(d+1,d+n+1);
sort(k+1,k+m+1);//排序
for(int i=1;i<=n;i++)
{
bool Can_Kill=false;//用来存储能不能砍掉龙头
for(int j=1;j<=m;j++)
{
if(used[j]) continue;//used数组存储龙头是否已经被砍
if(k[j]>=d[i])//由于排序过,所以第一个能砍的必然是能砍的最小的头
{
ans+=k[j];//费用加上
Can_Kill=true;//能杀
sum++;//又杀了一头
used[j]=true;//这头龙已死
break;//退出循环
}
}
if(!Can_Kill)//不能杀的话直接 欢声笑语中打出GG
{
printf("you died!");
return 0;
}
}
if(sum==n) printf("%d",ans);
else printf("you died!");//判断输出即可
return 0;
}
小结
贪心不论是在 日常刷题 还是在 竞赛 中,使用都非常广泛
相信参加过竞赛(甚至是模拟赛)的同学都知道贪心是一种十分优秀的骗分方法
所以贪心还是有必要多学多练的
原创 By Venus
写的不好大佬轻喷