机智零崎不会没梗Ⅰ (贪心算法)
题目描述
之前的上机中,背包问题已经基本都和大家混了个脸熟,不过还有一种不是背包却以背包为名的问题,零崎只能说“我从未见过如此厚颜无耻之包”。梗玩过了,就进入正题。
M87星云盛产矿物,有红色的绿色的黄色的蓝色的银色的白色的……不同颜色的矿物产量不同用途不同自然价值也不一样。隔壁M78星云的人虽然说主要是用银色的做头盔,不过其他颜色的还可以拿来卖给地球人啊23333
某外星生物一次可以携带重量为G的矿物,现在他们面前有K块重量W,价值V的矿石,不过他们很厉害所以可以把矿石搓成矿砂再把矿砂搓成矿石。
外星生物穿越星际路费可是很贵的,如果他们带来的矿石价值不足N,则请你补足路费,否则你只要大喊一声summon,他们就会出现了!
输入
多组输入数据
第一行为三个整数,分别为描述中的G K N
接下来K行,每行两个整数为W,V。
K小于10000,其他数据保证在int范围内,且W不为0
输出
对于每组数据,输出一行,为“summon!”或者需要补充的路费,结果保留3位小数。
输入样例
3 2 1
1 2
2 3
1 1 10
1 5
输出样例
summon!
5.000
题目来源:http://biancheng.love/contest/23/problem/B/index
解题思路:贪心算法。
根据题目可知,既然外星人可以把矿石搓成矿砂再把矿砂搓成矿石,那么我们所要做的就是:求出外星人在最大载重为G时,携带矿石价值的最大值。如果该最大值比N小,需要输入路费也就是差了多少钱,如果大于N,输出summon! 那么本体的关键在于求出最大价值。
下面分析最大值如何求解:
1、将矿石的性价比进行排序(所谓性价比也就是单位质量矿石的价格),外星人每次将矿砂搓成矿石的顺序按照矿石的性价比依次进行。
2、将矿砂逐个搓成矿石,放入外星人的口袋中,同时这种矿石的数量减一。(意思就是外星人只能还原矿石不能把原来性价比为1的矿石搓成性价比为100的矿石)。
3、在外星人将矿石放到自己的口袋的时候,需要帮助他判断是否能够装得下。同时我们还要记下一笔帐:这个外星人现在装的矿石价值总共是多少。
4、输出的判断。判断最大值和N之间的关系。输出格式printf("%.3lf\n",N-ans); 或者输出printf("summon!\n");
通过上述的讲解,我们在对矿石的性价比排序的时候可以采用结构体的形式。包括矿石的价值,数量,性价比。
给出本题的代码:
1 #include <bits/stdc++.h> 2 using namespace std; 3 struct node{ 4 double w; 5 double v; 6 double temp; 7 }; 8 9 bool cmp(node a,node b) 10 { 11 return a.temp>b.temp; 12 }; 13 14 int main() 15 { 16 int K; 17 double G,N,ans; 18 while(~scanf("%lf%d%lf",&G,&K,&N)) 19 { 20 ans=0; 21 node no[K]; 22 for(int i=0;i<K;i++) 23 { 24 scanf("%lf%lf",&no[i].w,&no[i].v); 25 no[i].temp=no[i].v/no[i].w; 26 } 27 sort(no,no+K,cmp); 28 for(int i=0;i<K;i++) 29 { 30 if(G>=no[i].w) 31 { 32 ans+=no[i].v; 33 G-=no[i].w; 34 } 35 else 36 { 37 ans=ans+G*(no[i].temp); 38 G=0; 39 } 40 } 41 if(ans>=N) 42 printf("summon!\n"); 43 else 44 printf("%.3lf\n",N-ans); 45 } 46 }
作者: 伊甸一点
出处: http://www.cnblogs.com/zpfbuaa/
本文版权归作者伊甸一点所有,欢迎转载和商用(须保留此段声明),且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利.
原文链接 如有问题, 可邮件(zpflyfe@163.com)咨询.