恰好裝滿,表示空間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; }
結果是與上個表格的最后一行一致的。