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 }

 

posted @ 2021-07-14 15:58  永远是个小孩子  阅读(156)  评论(0编辑  收藏  举报