0、1背包问题:
题目:有N件物品和一个容量为V的背包。第i件物品的价值是value[i],重量是weight[i].求解将哪些物品装入背包使价值总和最大。
思路:
这是最基本的01背包问题,特点是每种物品仅有一件,可以选择放还是不放。
状态转移方程:
f[ i ][ v ]表示前i件物品放入一个背包容量为v的背包可以获得的最大价值。
f[i][v] = max(f[i-1][v], f[i-1][v-weight[i]]+value[i])
其表示的含义是第i个物品所占V个空间,如果不放入第i个物品则f[i][v] = f[i-1][v],如果放入第i个物品,f[i][v] = f[i-1][v-weight[i]]+value[i];这个意思表示第i-1个物品占据的空间是v-weight[i],因为有一部分要放第i个物品。
其时间复杂度和空间复杂度都是O(N*V),但是空间复杂度可以优化为O(V)也就是用一维数组存储。
一维状态转移方程:
for(int i=1;i<=N;i++){
for(int v = V;v>=0;v–){
f[v] = max(f[v],f[v-weight[i]]+value[i])
}
}
注意这里第二个循环的方程是从V到0,因为如果V是从小到大的,那么会出现重复加value的情况,例如初始是空的,weight都是2.
这个状态转移方程的意思是,放第i个物品,放在空间为v的背包当中,如果可以放下,那么就是f[v-weight[i]]+value[i],这里的f[v-weight[i]]表示第i个物品占据了weight[i],那么就还剩下i-weight[i]的空间放别的物品,而放第i个的时候,并没有更新f[i-weight[i]]的值,如果不放则还是f[i].