题目描述
阿里巴巴走进了装满宝藏的藏宝洞。藏宝洞里面有 N(N≤100) 堆金币,第 $i$ 堆金币的总重量和总价值分别是 mi,vi(1≤mi,vi≤100)。阿里巴巴有一个承重量为 T(T≤1000)的背包,但并不一定有办法将全部的金币都装进去。他想装走尽可能多价值的金币。所有金币都可以随意分割,分割完的金币重量价值比(也就是单位价格)不变。请问阿里巴巴最多可以拿走多少价值的金币?
输入格式
第一行两个整数 N,T。
接下来 N 行,每行两个整数 mi,vi。
输出格式
一个实数表示答案,输出两位小数
样例输入
4 50
10 60
20 100
30 120
15 45
样例输出
240.00
总结如下:
这是一个经典的背包问题,可以使用动态规划算法来解决。
首先,我们定义一个二维数组 dp,其中 dp[i][j] 表示在前 i 堆金币中,背包容量为 j 时能够获取的最大价值。
然后,我们可以使用以下递推关系式来计算 dp[i][j]:
当 i=0 或 j=0 时,dp[i][j] = 0,表示没有金币或背包容量为 0,无法获取任何价值。
当 j < mi 时,dp[i][j] = dp[i-1][j],表示当前背包容量无法容纳第 i 堆金币,所以最大价值与前 i-1 堆金币的最大价值相同。
当 j ≥ mi 时,dp[i][j] = max(dp[i-1][j], dp[i-1][j-mi] + vi),表示可以选择装入第 i 堆金币或不装入第 i 堆金币,取两者中的最大值作为最大价值。
最后,dp[N][T] 就是阿里巴巴最多可以拿走的金币的最大价值。
代码如下:
#define _CRT_SECURE_NO_WARNINGS
#include<bits/stdc++.h>
#include<iostream>
using namespace std;
int n, t;
struct node {
int w;
int v;
}a[110];
double s;
bool cmp(node& a, node& b) {
return a.v * b.w > b.v * a.w;
}
int main() {
cin >> n >> t;
for (int i = 1; i <= n; i++)
cin >> a[i].w >> a[i].v;
sort(a + 1, a + 1 + n, cmp);
for (int i = 1; i <= n; i++) {
if (t >= a[i].w) {
s += a[i].v;
t -= a[i].w;
}
else {
s += 1.0 * t * a[i].v / a[i].w;
break;
}
}
printf("%.2lf", s);
return 0;
}