zoukankan      html  css  js  c++  java
  • 矩阵(01背包+滚动数组)

    题意:

    有一个(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
    ",ans);
        return 0;
    }
    
    

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

  • 相关阅读:
    一个通用的事件监听函数全集
    单应性矩阵
    opencv姿态估计
    opencv相机标定
    Harris角点
    盒滤波Box Filter
    win10+vs2015+pcl1.8.1安装配置
    图像元素遍历
    阈值分割
    二叉树的层次遍历
  • 原文地址:https://www.cnblogs.com/PPXppx/p/10328090.html
Copyright © 2011-2022 走看看