有N件物品和一件容量为V的背包。第i件物品的费用是c[i],价值是w[i]。问将那些物品装入背包获得的价值最大。
状态 f[i][v]表示将前i件物品放入容量为v的背包中,获得的最大价值为f[i][v]。
状态转移方程为 f[i][v] = max{f[i-1][v], f[i-1][v-c[i]] + w[i]}。
时间和空间复杂度为O(NV)。
空间复杂度的优化:若f[i-1][v]被f[v]代替,f[i-1][v-c[i]]被f[v-c[i]]代替,那么再求f[i][v]时,可以f[v]= max(f[v],f[v-c[i]])(此时max里的f[v]已知,而外的f[v]未知)。由于外层的循环是由i-1到i,若内层V的循环也是由小到大,那么计算f[v]= max(f[v],f[v-c[i]])时,f[c-v[i]]此时就是f[i][v-c[i]],而不是f[i-1][v-c[i]]。所以内层v的循环从大到小,此时i-1循环完后f[v],f[v-c[i]]分别相当于f[i-1][v],f[i-1][v-c[i]]。
优化后的空间复杂度为O(V)。
初始化问题:
若要求将背包恰好完全装满,则f[0] = 0, f[1...v] = 负无穷。
若无此要求,则f[0....V]= 0.
可以这样理解:初始化的f数组事实上就是在没有任何物品可以放入背包时的合法状态。如果要求背包恰好装满,那么此时只有容量为0的背包可能被价值为0的nothing“恰好装满”,其它容量的背包均没有合法的解,属于未定义的状态,它们的值就都应该是-∞了。如果背包并非必须被装满,那么 任何容量的背包都有一个合法解“什么都不装”,这个解的价值为0,所以初始时状态的值也就全部为0了。