0-1背包算法 plus 空间复杂度优化版

来源:互联网 发布:张明淳 工程矩阵答案 编辑:程序博客网 时间:2024/06/05 23:29

问题描述:在M件物品取出若干件放在空间为W的背包里,每件物品的体积为volume[1],volume[2]……volume[n],与之相对应的价值为value[1],value[2]……value[n]。物品不可分割。


算法:动态规划。dp[i][j]表示有i件物品,背包大小为j的时候能拿走物品的最大价值,那么,

dp[i][j]=max(dp[i-1][ j-volume[i] ]+value[i] , dp[i-1][j]).

意思就是,如果不拿第i件物品,获得的价值就跟有i-1件物品获得的价值一样,否则获得的价值就是有前i-1件物品,背包容量为(j-物品i的体积)的时候获得的价值 + 物品i的价值。取其中的较大者。

代码如下:


int value[MAXSIZE],volume[MAXSIZE];int dp[MAXSIZE][MAXSIZE];int n,size;int zeroOnePack(){    int i,j;    for(i=0; i<=n; i++)dp[i][0] = 0;    for(j=0; j<=size; j++)dp[0][j] = 0;    for(i=1; i<=n; i++)        for(j=1; j<=size; j++)        {            dp[i][j] = dp[i-1][j];            if(j>=volume[i] && dp[i-1][j-volume[i]]+value[i] > dp[i][j])                dp[i][j] = dp[i-1][j-volume[i]]+value[i];        }    return dp[n][size];}

时间、空间复杂度都是 O(n*size)


不过,我们可以在空间复杂度上做一些优化。

观察状态转移方程dp[i][j]=max(dp[i-1][ j-volume[i] ]+value[i] , dp[i-1][j]),dp[i][j]只与第i-1行的dp有关,而且只与dp[i-1][x] (0 <= x <= j)有关。因此可以把dp缩小成一维数组,每次遍历dp之后保留的就相当于是第i-1行的值。同时,把j=1...size的遍历改成j=size...volume[i](0至volume[i]-1的背包空间对体积为volume[i]的物品拿不拿没影响),这样计算dp[j]的时候就不必担心dp[x](0 <= x <= j)被改动过。

下面给出代码:

int value[MAXSIZE],volume[MAXSIZE];int dp[MAXSIZE];int n,size;int zeroOnePack(){    int i,j;    memset(dp,0,(size+1)*sizeof(int));    for(i=1; i<=n; i++)        for(j=size; j>=volume[i]; j--)        {            if(dp[j-volume[i]]+value[i] > dp[j])                dp[j] = dp[j-volume[i]] + value[i];        }    return dp[size];}

这样真的可以节省不少内存,希望对大家有帮助。。。

原创粉丝点击