码迷,mamicode.com
首页 > 编程语言 > 详细

矩阵(01背包+滚动数组)

时间:2019-01-28 00:57:24      阅读:237      评论:0      收藏:0      [点我收藏+]

标签:lse   cpp   背包   复杂度   复杂   表示   数组   容量   max   

题意:

有一个\(n×m\)的矩阵,你从左上角走到右下角,只能向下和向右走.每个点上有一个重量\(v_{i,j}\) 价值\(w_{i,j}\)的物品,你有一个容量为S的背包,经过一个点你可以将此点的物品放入背包,求最大能得到的价值.

分析:

\(f_{i,j,k}\)表示走到\((i,j)\),背包剩余容量为 k 时的最大价值.

\(f_{i,j}\)\(f_{i-1,j}\)\(f_{i,j-1}\)按普通 01 背包的方法转移.

时间复杂度 \(O(N^2V)\),空间复杂度 \(O(N^2V)\).因为\(400^3\)可能会爆空间MLE,所以我们可以按行或对角线滚动数组(我是按行滚动的),这样空间复杂度\(O(NV)\).

int n,m,S,ans;
int v[405][405],w[405][405],f[405][405];
//v重量,w价值
int main(){
    n=read();m=read();S=read();
    for(int i=1;i<=n;i++)
    for(int j=1;j<=m;j++)
        v[i][j]=read();
    for(int i=1;i<=n;i++)
    for(int j=1;j<=m;j++)
        w[i][j]=read();
    for(int i=1;i<=n;i++)
    for(int j=1;j<=m;j++)
    for(int k=S;k>=0;k--){
        if(k>=v[i][j])f[j][k]=max(f[j][k],max(f[j][k-v[i][j]]+w[i][j],max(f[j-1][k],f[j-1][k-v[i][j]]+w[i][j])));
        else f[j][k]=max(f[j][k],f[j-1][k]);
    }
//因为题目中说了"只能向下和向右走",
//所以对于第i行的状态,一定只能由第i-1行转移得来,
//所以此时我们可以滚掉第一维i.
    for(int i=0;i<=S;i++)
        ans=max(ans,f[m][i]);
    printf("%d\n",ans);
    return 0;
}

滚动数组是动态规划,尤其是背包问题中很重要的一个思想,它虽然不能优化时间复杂度,但它能够减少空间复杂度.因为有时候可能题目会故意卡你的空间,所以我们要掌握好.

矩阵(01背包+滚动数组)

标签:lse   cpp   背包   复杂度   复杂   表示   数组   容量   max   

原文地址:https://www.cnblogs.com/PPXppx/p/10328090.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!