简单贪心
贪心法是求解一类最优化问题的方法,它总是考虑在当前状态下局部最优或较优的策略,来使全局达到最优或较优
例题1 【PAT B1020 月饼】
题目描述
现给出所有种类月饼的库存、总售价以及市场的最大需求量,试计算可以获得的最大收益。
注:销售时允许取出一部分库存
案例情形如下:有三种月饼,其库存量分别为18、15、10万吨,总售价分别为75、72、45亿元。若市场需求量只有20万吨,则最大收益策略应当是卖出全部15万吨第二类月饼和5万吨第三种月饼,获得94.5亿元
输入格式
每个输入包含一个测试用例,每个测试用例先给出一个不超过1000的正整数N表示月饼的种类数,以及不超过500(万吨)的正整数D表示市场的最大需求量,随后一行给出N个正数表示表示每种月饼的库存量(万吨);最后一行给出N个整数表示每种月饼总售价(亿元)。数字间以空格分隔
输出用例
对每组测试用例,在一行中输出最大收益,以亿元为单位并精确到小数点后两位
样例输入
3 20
18 15 10
75 72 45
样例输出
94.50
解决方案
思路:
1.采取总是选择单价最高的月饼出售的策略,对每种月饼,根据总售价和库存量获得其单价,并根据单价依次排序
2.从单价高的月饼开始枚举,最后得到的收益即为最大收益
#include<cstdio>
#include<algorithm>
using namespace std;
struct mooncake {
double store; //库存
double sell; //总售价
double price; //单价
} cake[1010];
bool cmp(mooncake a, mooncake b)
{
return a.price > b.price;
}
int main()
{
int N;
double D;
scanf("%d %lf",&N,&D);
for (int i = 0; i < N; i++)
{
scanf("%lf",&cake[i].store); //为每种月饼的库存量赋值
}
for (int i = 0; i < N; i++)
{
scanf("%lf",&cake[i].sell); //为每种月饼的总售价赋值
cake[i].price = cake[i].sell/cake[i].store; //获得每种月饼的单价
}
sort(cake,cake + N,cmp); //对cake中mooncake根据单价从高到低排序
double ans = 0;
for (int i = 0; i < N; i++)
{
if (cake[i].store <= D) //当前月饼库存小于当前需求量
{
D -= cake[i].store; //更新需求量
ans += cake[i].sell;
}
else //当前月饼库存大于当前需求量
{
ans += cake[i].price * D;
break;
}
}
printf("%.2f",ans);
return 0;
}
例题2 【PAT B1023 组个最小数】
题目描述
给定数字 0 ~ 9 各若干个,可以任意顺序排列这些数字,但必须全部使用。目标是使最后得到的数尽可能的小(0不能作为首位)。现编写程序,使最后得到的数尽可能的小。
输入格式
每个输入包含一个测试用例,每个测试用例在一行中给出是个非负整数,数字表示所拥有的 0 ~ 9 的数字的个数。整数间用一个空格分隔。十个数字的个数不超过50个,且至少包含一个非零数字
输出用例
在一行中输出能够组成的最小数字
样例输入
2 2 0 0 0 3 0 0 1 0
样例输出
10015558
解决方案
思路:
1.由于首位不能为0,因此先从 1 ~ 9 中选出个数不为0的最小数输出。然后从0到9依次将数量不为0的数根据其数目输出
#include<cstdio>
int num[15] = {0};
int main()
{
int startNum;
for (int i = 0; i < 10; i++)
{
scanf("%d",&num[i]);
}
for (int i = 1; i < 10; i++)
{
if (num[i] > 0)
{
startNum = i;
printf("%d",i);
num[i]--;
break;
}
}
for (int i = 0; i < 10; i++)
{
for (int j = 0; j < num[i]; j++)
{
printf("%d",i);
}
}
return 0;
}
区间贪心(待补充)
区间贪心,即区间不相交问题:给出N个开区间(x,y),从中选择尽可能多的开区间,使得这些开区间之间两两没有交集