用滚动数组求解0/1背包问题(此处仅求装入背包的最大价值)
//
由于第i个阶段(考虑物品i)的解dp[i][ * ]只与第i-1个阶段(考虑物品i-1)的解dp[i-1][ * ]有关,这种情况下保存更前面的数据已经毫无意义。
因此可以利用滚动数组进行优化,将dp数组由dp[MAXN][MAXN]改为dp[2][MAXN]。
因此0/1背包问题的状态转移方程如下:
dp[0][0]=0,dp[1][0]=0
dp[0][r]=0
dp[c][r]=dp[1-c][r] (当r<w[i]时,物品i放不下)
dp[c][r]=MAX{dp[1-c][r],dp[1-c][r-w[i]]+v[i]}
(否则在不放入和放入物品i之间选择最优解)
代码实现:
#include<stdio.h>
#define MAXN 20
#define MAXW 100
int n=5,W=10;
int w[MAXN]={0,2,2,6,5,4};
int v[MAXN]={0,6,3,5,4,6};
int dp[1][MAXW];
int max(int a,int b){
return a>b?a:b;
}
void Knap(){
int i,r;
int c=0;
for(int i=0;i<=1;i++)
dp[i][0]=0;
for(int r=0;r<=W;r++)
dp[0][r]=0;
for(int i=1;i<=n;i++){
c=1-c;
for(int r=1;r<=W;r++){
if(r<w[i]) dp[c][r]=dp[1-c][r];
else
dp[c][r]=max(dp[1-c][r],dp[1-c][r-w[i]]+v[i]);
}
}
}
int main(){
Knap();
printf("总价值=%d\n",max(dp[0][W],dp[1][W]));
return 0;
}
参考自《算法设计与分析》第二版 李春葆