宝藏
这个题目是一个双01背包dp
这是我40分的代码
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define endl '\n'
const int N=2010;
ll n,v1,v2;
ll v[N],w[N],f[N][N],g[N][N];
int main(){
cin.tie(0)->sync_with_stdio(0);
//freopen("treasure.in","r",stdin);
//freopen("treasure.out","w",stdout);
cin>>n>>v1>>v2;
for(int i=1;i<=n;i++) cin>>v[i]>>w[i];
for(int i=1;i<=n;i++){
for(int j=0;j<=v1;j++){
for(int k=0;k<=v2;k++){
g[j][k]=0;
}
}
for(int j=0;j<=v1;j++){
for(int k=0;k<=v2;k++){
g[j][k]=f[j][k];
if(j>=v[i]) g[j][k]=max(f[j][k],f[j-v[i]][k]+w[i]);
if(k>=v[i]) g[j][k]=max(f[j][k],f[j][k-v[i]]+w[i]);
}
}
for(int j=0;j<=v1;j++){
for(int k=0;k<=v2;k++){
f[j][k]=g[j][k];
}
}
}
cout<<f[v1][v2]<<endl;
return 0;
}
但是在转移的时候是有问题的
我们举一个例子
比如j和k都大于\(v_i\)并且j转移最大,k其次,不选最小
第一次j和不选比较的时候,答案是j。这是对的
但是第二次比较的时候,答案是k,会抹除上一次正确的j,导致错误!
正确代码因该是每一轮都是和g比较,不然会抹除正确答案
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define endl '\n'
const int N=2010;
ll n,v1,v2;
ll v[N],w[N],f[N][N],g[N][N];
int main(){
cin.tie(0)->sync_with_stdio(0);
freopen("treasure.in","r",stdin);
freopen("treasure.out","w",stdout);
cin>>n>>v1>>v2;
for(int i=1;i<=n;i++) cin>>v[i]>>w[i];
for(int i=1;i<=n;i++){
for(int j=0;j<=v1;j++){
for(int k=0;k<=v2;k++){
g[j][k]=0;
}
}
for(int j=0;j<=v1;j++){
for(int k=0;k<=v2;k++){
g[j][k]=f[j][k];
if(j>=v[i]) g[j][k]=max(g[j][k],f[j-v[i]][k]+w[i]);
if(k>=v[i]) g[j][k]=max(g[j][k],f[j][k-v[i]]+w[i]);
}
}
for(int j=0;j<=v1;j++){
for(int k=0;k<=v2;k++){
f[j][k]=g[j][k];
}
}
}
cout<<f[v1][v2]<<endl;
}

浙公网安备 33010602011771号