2484: 【例】【普及/提高-】【P2240】部分背包问题

内存限制:128 MB 时间限制:1.000 S
评测方式:文本比较 命题人:
提交:20 解决:18

题目描述

阿里巴巴走进了装满宝藏的藏宝洞。藏宝洞里面有 lns="http://www.w3.org/1998/Math/MathML">(100) 堆金币,第 lns="http://www.w3.org/1998/Math/MathML"> 堆金币的总重量和总价值分别是 lns="http://www.w3.org/1998/Math/MathML">,(1,100)。阿里巴巴有一个承重量为 lns="http://www.w3.org/1998/Math/MathML">(1000) 的背包,但并不一定有办法将全部的金币都装进去。他想装走尽可能多价值的金币。所有金币都可以随意分割,分割完的金币重量价值比(也就是单位价格)不变。请问阿里巴巴最多可以拿走多少价值的金币?

输入

第一行两个整数 lns="http://www.w3.org/1998/Math/MathML">,

接下来 lns="http://www.w3.org/1998/Math/MathML"> 行,每行两个整数 lns="http://www.w3.org/1998/Math/MathML">,

输出

一个实数表示答案,输出两位小数

样例输入 复制

4 50
10 60
20 100
30 120
15 45

样例输出 复制

240.00

提示


#include<cstdio>
#include<algorithm>
using namespace std;
struct coin {
    int m, v; // 金币堆的重量和价值
}
a[110];
bool cmp(coin x, coin y) {
    return x.v * y.m > y.v * x.m; //判断单价
}
int main() {
    int n, t, c, i;
    double ans = 0;
    scanf("%d%d", & n, & t);
    c = t; // 背包的剩余容量
    for (i = 0; i < n; i++)
        scanf("%d%d", & a[i].m, & a[i].v);
    sort(a, a + n, cmp); // 对单价排序
    for (i = 0; i < n; i++) {
        if (a[i].m > c) break; //如果不能完整装下就跳出
        c -= a[i].m;
        ans += a[i].v;
    }
    if (i < n)
        ans += 1.0 * c / a[i].m * a[i].v; // 剩余空间装下部分金币
    printf("%.2lf", ans);
    return 0;
}