01 背包问题
输入:
n个商品组成集合O,每个商品有两个属性vi和pi,分别表示体积和价格
背包容量为C
输出:
求解一个商品子集包含于O,令价格和最大,容量不超过C
直观上 : 价格高优先 , 体积小优先 , 性价比高优先 都不能得到最优解
解决方案一 : 蛮力枚举,递归求解(非DP)
递归函数:KnapsackSR(h,i,c) h: 首序号元素 i: 尾序号元素 c:剩余容量
knapsackSR(h,i,c) = max{ KnapsackSR(h,i-1,c-vi)+pi , knapsackSR(h,i-1,c) }
伪代码:
if c<0 then
return -1
end
if i<=h-1 then
return 0 商品规划完成
end
P1<--KnapsackSR(h,i-1,c-vi)
P2<--KnapsackSR(h,i-1,c)
P=max{P1+pi,P2}
return P
时间复杂度 : O(2^n)
解决方案二: 带备忘的递归方法(优化)
(DP,自顶向下)
KnapsackMR(h,i,c)
伪代码:
if c<0 then
return -1
end
if i<=h-1 then
return 0 商品规划完成
end
if P[i,c]!=NULL then
return P[i,c] 当P[i,c]有值返回就行
end
P1<--KnapsackMR(h,i-1,c-vi)
P2<--KnapsackMR(h,i-1,c)
P[i,c]=max{P1+pi,P2}
return P[i,c]
解决方案三: 递推求解
(DP,自底向上)
KnapsackDR(h,i,c)
伪代码:
//初始化
创建二维数组P[n][c]和Rec[n][c]
//第一行第一列都是0
for i<- 0 to C do
P[0,i]<-0
end
for i<- 0 to n do
P[i,0]<-0
end
//求解表格
for i<- 1 to n do
for c<- 1 to C do
if(vi<=c)and(pi+P[i-1,c-vi]>P[i-1,c]) then
P[i,c]<- pi+P[i-1,c-vi]
Rec[i,c]<- 1
end
else
P[i,c]<- P[i-1,c]
Rec[i,c]<- 0
end
end
end
//输出最优方案
K<- C
for i<- n to 1 do
if Rec[i,k] =1 then
print 选择商品i
K<- k-vi
end
else
print 不选商品i
end
end
return P[n,c]
时间复杂度 : O(n C)