[洛谷]P2240 【深基12.例1】部分背包问题

阿里巴巴面临一个部分背包问题,需要在承重量限制下最大化装走金币的总价值。每堆金币可任意分割,保持单位价格不变。问题通过计算每堆金币的单位价值并按降序排列,优先选取单位价值高的金币装入背包来解决。给出的代码实现了这一策略。

题目描述

阿里巴巴走进了装满宝藏的藏宝洞。藏宝洞里面有 N(N \le 100)N(N≤100) 堆金币,第 ii 堆金币的总重量和总价值分别是 m_i,v_i(1\le m_i,v_i \le 100)mi​,vi​(1≤mi​,vi​≤100)。阿里巴巴有一个承重量为 T(T \le 1000)T(T≤1000) 的背包,但并没办法将全部的金币都装进去。他想装走尽可能多价值的金币。所有金币都可以随意分割,分割完的金币重量价值比(也就是单位价格)不变。请问阿里巴巴最多可以拿走多少价值的金币?

输入格式

第一行两个整数 N、T
接下来 N 行,每行两个整数 m_i,v_imi​,vi​

输出格式

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

输入输出样例

输入 #1复制

4 50
10 60
20 100
30 120
15 45

输出 #1复制

240.00

【思路】

因为金币可以任意分割,我们不用担心因为背包的体积, 放入一个背包后, 无法放入其他背包。

步骤如下, 我们根据每组背包的总价值和体积,计算出每组背包的单位价格。并按照单位价格排序。

然后优先放入单位价值高的金币。直到背包容量为空为止。(因为背包可以分割,所以,如果背包剩余空间放不下一组的话,可以把这一组的金币分开存放。)

【代码】

#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
using namespace std;
struct Good {
    int w, v;
    double p;
    bool operator<(const Good & a) const {
        return p > a.p;
    }
};
const int  N = 105;
Good a[N];
int n, t;
double res;
int main() {
    cin >> n >> t;
    for(int i = 0 ;i < n; i++) {
        scanf("%d%d", &a[i].w, &a[i].v);
        a[i].p = double(a[i].v) / a[i].w;
    }
    sort(a, a + n);
    for(int i = 0 ;i < n; i++) {
        if(t > a[i].w) {
            res += a[i].v;
            t -= a[i].w;
        } else {
            res += t * a[i].p;
            break;
        }
    }
    printf("%.2lf", res);
    return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值