4110:圣诞老人的礼物,考点:贪心算法,排序
原题:http://bailian.openjudge.cn/practice/4110/
描述
圣诞节来临了,在城市A中圣诞老人准备分发糖果,现在有多箱不同的糖果,每箱糖果有自己的价值和重量,每箱糖果都可以拆分成任意散装组合带走。圣诞老人的驯鹿最多只能承受一定重量的糖果,请问圣诞老人最多能带走多大价值的糖果。
输入
第一行由两个部分组成,分别为糖果箱数正整数n(1 <= n <= 100),驯鹿能承受的最大重量正整数w(0 < w < 10000),两个数用空格隔开。其余n行每行对应一箱糖果,由两部分组成,分别为一箱糖果的价值正整数v和重量正整数w,中间用空格隔开。
输出
输出圣诞老人能带走的糖果的最大总价值,保留1位小数。输出为一行,以换行符结束。
样例输入
4 15 100 4 412 8 266 7 591 2
样例输出
1193.0
解法
思路:按礼物的价值/重量比从大到小一次选取礼物,尽可能多的装。
证明可以用贪心:替换法
注意:如果这道题中糖果不能拆开,只能整箱拿,那就不能用贪心法,只能用动态规划(类似于背包问题)
代码如下
1 #include <iostream> 2 #include <set> 3 #include <iomanip> 4 using namespace std; 5 struct candy { 6 int value; 7 int weight; 8 double vperw; 9 candy(int v, int w) :value(v), weight(w) { 10 vperw = double(value) / weight; 11 } 12 bool operator <(const candy A) const{ 13 return vperw > A.vperw; 14 } 15 }; 16 int main() 17 { 18 int n, w; 19 cin >> n >> w; 20 multiset<candy>alls; 21 for (int i = 0; i < n; i++) 22 { 23 int v, w; 24 cin >> v >> w; 25 alls.insert(candy(v, w)); 26 } 27 double weights = 0; 28 double values = 0; 29 multiset<candy>::iterator ii; 30 for (ii = alls.begin(); ii != alls.end(); ii++) { 31 if (ii->weight + weights <= w) { 32 weights += ii->weight; 33 values += ii->value; 34 } 35 else { 36 double rest = w - weights; 37 values += ii->vperw*rest; 38 weights += rest; 39 } 40 if (weights == w) 41 break; 42 } 43 cout << fixed << setprecision(1) << values << endl; 44 return 0; 45 }