【转】01背包 多重背包 完全背包 二维压一维

此文上接:

1、记忆化搜索与动态优化与背包问题
https://blog.csdn.net/qq_28120673/article/details/81037700
2、使用递推关系的动态规划dp解决问题(最长公共子序列和完全背包问题)
https://blog.csdn.net/qq_28120673/article/details/81043671

通过上面的讨论,已近解决了动态规划的使用问题。上面的背包问题中,我们使用了二维数组来存储规划过程,基本上可以说动态规划是利用空间换取时间的方法。在计算中可以发现其实数组是可以重复使用的,我们可以只是用一行数组记录动态规划过程。

在01背包问题中,将dp[MAX_N+1][MAX_N+1]改为dp[MAX_N+1]。在i的每次循序将第二行数据覆盖第一行。
其算法如下:

int dp[MAX_W+1];
void solve(){
    for(int i=0;i<n;i++){
        for(int j=W;j>=w[i];j--){
            dp[j]=max( dp[j],dp[j-w[i]]+v[i]);
        }
    }
    cout<<dp[w]<<endl;;
}

完全背包问题中有类似的方法:
代码如下:

int dp[MAX_W+1];
void solve(){
    for(int i=0;i<n;i++){
        for(int j=w[i];j<=W;j++){
            dp[j]=max(dp[j],dp[j-w[i]]+v[i]);
        }
    }
    cout<<dp[W];
}

仔细观察方向,这两个算法的差别在于循环方向不同。

多重背包:和01差不多,要多加一个for表示当前物品数量

cin >> n >> m;
    for(ll i = 1; i <= n; i++)
        cin >> A[i].w >> A[i].value >> A[i].num;

    for(ll i = 1; i <= n; i++)
        for(ll j = 1; j <= A[i].num; j++)
            for(ll k = m; k >= A[i].w; k--)
    {
        DP[k] = max(DP[k],DP[k-A[i].w]+A[i].value);
    }
    cout << DP[m] << endl;

猜你喜欢

转载自blog.csdn.net/Whyckck/article/details/81586073