恰好装满,表示空间V完全被占用。
之前的题目是说,在不超过空间V的情况下,使价值最大化。
现在考虑动态规划的初始值问题。
在前一个问题中,dp[i][v]初始化设置为0.
因为在初始状态,背包中没有任何物品。不论背包的容量多大,里面的价值只是0.这个状态是合法的。因为背包并没有超出容量。
现在,背包只有完全占满才是合法的值。那么在初始状态,dp[i][0]=0是合法的,因为容量为0,不放任何东西就是合法了。
其他的都是非法值。应该设置为负无穷。
const int INF = 0x3f3f3f3f; const int NINF= -INF - 1; int main() { int n = 5; int sum = 12; int w[5] = {5, 4, 7 ,2 ,6}; int p[5] = {12,3,10, 3, 6}; int dp[6][13]; int i,v; memset(dp,NINF,sizeof(dp)); dp[0][0] = 0; for(i = 1; i <= n ; i++) { dp[i][0] = 0; for(v = 1;v <= sum; v++) { if(v >= w[i-1]) dp[i][v] = max_2( dp[i-1][v-w[i-1]] + p[i-1],dp[i-1][v] ); else dp[i][v] = dp[i-1][v]; } } for(i = 1; i <= n ; i++) { for(v = 0;v<=sum;v++) { if(dp[i][v] < 0) printf("X "); else printf("%d ",dp[i][v]); } printf("\n"); } return 0; }
运行结果如下:
可以看到,背包容量为0时,总有合法值。因为只要不放就是合法的。
容量为1时,由于没有体积为1的物品,所以v=1的所有状态都是非法的。取值为负无穷。
V=2时,由于物品4的体积为2,所以前4件 和 前5件,都有合法值。
以此类推。
空间优化后使用一维数组的代码:
int main() { int w[5] = {5, 4, 7 ,2 ,6}; int p[5] = {12,3,10, 3, 6}; int i,v,n = 5; int sum = 12; int dp[13]; memset(dp,NINF,sizeof(dp)); dp[0] = 0; for(i=0;i<n;i++) { for(v=sum;v>=w[i];v--) // v不够w[i]的话,dp[v]不会改变。 { dp[v] = max_2( dp[v], dp[v-w[i]]+p[i] ); } } for(i = 0;i<=sum;i++) { printf("%d ",dp[i]); } return 0; }
结果是与上个表格的最后一行一致的。