宝藏

题目传送门

这个题目是一个双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;
}
posted @ 2026-01-24 11:46  zhangruotian_Max  阅读(1)  评论(0)    收藏  举报