Openjudge-4110-圣诞老人的礼物

这一题是一道贪心的题目,但是它比较特殊的地方在于糖果可以分开拿,我们不必整箱拿,所以我们可以直接就把糖果按照价值比从大到小排序,然后整箱装不下的时候,剩余重量乘以它的价值比,这样就算出来了。

对于结构体的排序,这里的重载就是运算符的重载,这个结构体很像类。我们不必接受两个参数,直接只接收后一个,然后进行比较即可。

这个贪心直观看上去是正确的,下面我们来证明一下:

我们假设你觉得的一个价值最大的糖果拿法,它的序列是 A ,我们按照价值比拿的糖果序列为 B ,我们将 A 序列按照价值比降序排列。

我们比较 A i  和  B i ,如果它们相等,我们就向后比较,直到第一个不相等的,那一定是 Bi 大于 Ai,因为 Bi 是按价值比从大到小排列的,除非你也是这样选的,否则你选的肯定要小于 Bi 。

那这样的话,Ai就可以用Bi替换,我们此时就可以选择Bi,不再选择Ai,但是这时候 A 序列的价值就增加了,这和它是最大价值序列矛盾,所以按照价值比降序排列的取法就是正确的。

#include <iostream>
#include <algorithm>
using namespace std;
const double eps=1e-6;
 
struct Candy {
    int v,w;
    bool operator < (const Candy &c)
    {
        return double(v)/w-double(c.v)/c.w>eps;
    }
}candy[110];
 
int main()
{
    int N,W;
    cin>>N>>W;
    for (int i=0;i<N;i++) {
        cin>>candy[i].v>>candy[i].w;
    }
    double totalV=0;
	int totalW=0;
    sort(candy,candy+N);
    for (int i=0;i<N;i++) {
        if (totalW+candy[i].w<W) {
            totalW+=candy[i].w;
            totalV+=candy[i].v;
        }
        else {
            totalV+=double(candy[i].v)/candy[i].w*(W-totalW);
            break;
        }
    }
    printf("%.1lf\n",totalV);
    return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_41090676/article/details/84841435
今日推荐