4733: 【GESP2512六级】道具商店
内存限制:512 MB
时间限制:1.000 S
评测方式:文本比较
命题人:
提交:3
解决:3
题目描述

样例输入 复制
3 5
99 1
33 2
11 3
样例输出 复制
132
提示
题意分析
01 背包变形题。
- n 最多 500,每个道具攻击力\(a_i \le 500\),总攻击力最大 = 500*500 = 250000
- 但是金币 k、花费\(c_i\)可以到\(10^9\),不能把金币作为 dp 数组下标(普通 01 背包过不去)。
普通 01 背包:dp[cost]=max_val,这里反过来:
dp[x]= 获得x 点攻击力,需要花费的最少金币。
最后遍历所有攻击力 x,找到最大的 x 满足dp[x] ≤ k,就是答案。
#include <iostream>
#include <algorithm>
using namespace std;
typedef long long ll;
const ll INF = 1e18;
const int MAXA = 500 * 500; // 250000
ll dp[250010];
int main()
{
int n;
ll k;
cin >> n >> k;
// dp初始化
for(int i = 0; i <= MAXA; i++) dp[i] = INF;
dp[0] = 0;
for(int i = 1; i <= n; i++)
{
int a; ll c;
cin >> a >> c;
// 01背包倒序
for(int j = MAXA; j >= a; j--)
{
if(dp[j - a] != INF)
{
dp[j] = min(dp[j], dp[j - a] + c);
}
}
}
// 找最大攻击力,花费<=k
int ans = 0;
for(int x = MAXA; x >= 0; x--)
{
if(dp[x] <= k)
{
ans = x;
break;
}
}
cout << ans << endl;
return 0;
}
#include <cstdio>
#include <algorithm>
using namespace std;
const int N = 505;
const int oo = 1e9 + 10;
int n, k;
int f[N * N];
int main() {
scanf("%d%d", &n, &k);
for (int i = 1; i < N * N; i++)
f[i] = oo;
int s = 0;
for (int i = 1; i <= n; i++) {
int a, c;
scanf("%d%d", &a, &c);
s += a;
for (int j = s; j >= a; j--)
f[j] = min(f[j], f[j - a] + c);
}
int ans = 0;
for (int i = 0; i < N * N; i++)
if (f[i] <= k)
ans = i;
printf("%d\n", ans);
return 0;
}