思路
subtask1
直接暴力搜索即可。
subtask2
普通的 01 背包,直接 \(dp\) 即可。
subtask3
改变 \(dp\) 的状态,设 \(dp_i\) 表示价值为 \(i\) 时用的最小体积,那么就直接在里面找最小值就行。
代码
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
typedef long long ll;
const int N = 200005;
ll n, W, v[N], w[N];
bool A = 1, B = 1;
ll dp[N];
ll ans;
void dfs(int x, ll sp, ll sum) {
if (x > n) {
ans = max(ans, sum);
return ;
}
if (w[x] <= sp)
dfs(x + 1, sp - w[x], sum + v[x]);
dfs(x + 1, sp, sum);
}
int main() {
scanf("%lld%lld", &n, &W);
for (int i = 1; i <= n; i++) {
scanf("%lld%lld", &v[i], &w[i]);
if (w[i] > 1000) A = 0;
if (v[i] > 1000) B = 0;
}
if (!A && !B) {
dfs(1, W, 0);
printf("%lld\n", ans);
}
else if (A) {
for (int i = 1; i <= n; i++) {
for (int j = W; j >= w[i]; j--)
dp[j] = max(dp[j], dp[j - w[i]] + v[i]);
}
for (int i = 1; i <= W; i++)
ans = max(ans, dp[i]);
printf("%lld\n", ans);
}
else {
memset(dp, 0x3f, sizeof(dp));
dp[0] = 0;
long long sumv = 0;
for (int i = 1; i <= n; i++)
sumv += v[i];
for (int i = 1; i <= n; i++) {
for (int j = 200000; j >= v[i]; j--) {
dp[j] = min(dp[j], dp[j - v[i]] + w[i]);
}
}
for (int i = 1; i <= 200000; i++)
if (dp[i] <= W)
ans = i;
printf("%lld\n", ans);
}
return 0;
}
标签:問題,int,题解,ll,ABC032D,ans,include,dp
From: https://www.cnblogs.com/panda-lyl/p/18608746