0-1背包问题:给定的n种物品和一背包。物品i的重量是wi,其价值为vi,背包的容量为C。问:应该如何选择装入背包的物品,使得装入背包中物品的总价值最大?
【分析】
对于物品来说只有两种选择装入背包或者不装入背包即0-1,如何判断物品是否装入背包是0-1背包问题的核心。
用数组total[i][j]表示处理第i个物品后背包容量还有j时的总价值
可得到total[i][j] = Max(total[i-1][j-wi]+vi , total[i-1][j])
如果物品i放入背包total[i][j] = total[i-1][j-wi]+vi
如果物品i不放入背包total[i][j] = total[i-1][j]
最简单直接的方法是利用递归,但是递归计算比较多数据时很慢
【动态规划】
动态规划→记忆化搜索
动态规划→没计算则计算,计算过则保存
动态规划重要的是如何存储实现记忆化搜索
使用数组package[][]表示背包,用来存储数据实现记忆化搜索
eg:总容量capacity = 10
重量weight[6] = {0,2,2,6,5,4} (第一个元素的0可以去掉)
价值 value[6] = {0,6,3,5,4,6} (第一个元素的0可以去掉)
背包package[i][j]
求背包能装的物品总价值最大,即是求package[5][10]
package[i][]表示对第i个物品的处理-放或者不放
package[][j]表示背包容量为j的时候
//初始化数组,表格第一行第一列都为零
for(i=0;i<6;i++)
package[i][0] = 0;
for(j=0;i<11;j++)
package[0][j] = 0;
//判断是否需要存入背包,和纪录背包内物品的总价值
for(i=1;i<6;i++)
{
for(j=1;j<11;j++)
{
if(w[i]>j)
package[i][j] = package[i-1][j];
else if(package[i-1][j-w[i]]+v[i] > package[i-1][j])
package[i][j] = package[i-1][j-w[i]]+v[i];
else
package[i][j] = package[i-1][j];
}
}
【逆推求解】
有的题目加强一点难度,要求求出加入背包的物品是那些,需要用回溯的方法寻找加入背包的物品
用数组flag[6]表示五个物品是否放入背包,即0-不放入,1-放入
int tem = capacity;
for(int t=5;t>0;t++)
{
if(package[t-1][tem-w[t]]+v[t] > package[t-1][t])
{
flag[t] = 1;
tem = tem-w[t];
}
else
flage[t] = 0;
}