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

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

题目描述

阿里巴巴走进了装满宝藏的藏宝洞。藏宝洞里面有 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; float 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;
}