【问题描述】
已知有n种物品和一个可容纳M重量的背包,每种物品i的重量为W,假定将物品i的一部分Xi放人背包就会得到PiXi的效益,这里,o≤Xi≤1,Pi>0。采用怎样的装包方法才会使装入背包物品的总效益最大 。
【问题分析】
首先建立该问题的数学模型:
极大化: (1)
约束条件: (2)
其中,(1)式是目标函数,(2)和(3)是约束条件。满足约束条件的任一集合(x1…xn)是一个可行解(即能装下),使目标函数取最大值的可行解是最优解。
例1. 考虑下列背包问题:n=3,M=20,(p1,p2,p3)=(25,24,15),(w1,w2,w3)=(18,15,10)。其中的四个可行解是
(xl,x2,x3) 总容量 总效益
(1) (1/2,1/3,1/4) 16.5 24.25
(2) (1,2/15,0) 20 28.2
(3) (0,2/3,1) 20 31
(4) (0,1,1/2) 20 31.5
每一次装入的物品应使它占用的每一单位容量获得当前最大的单位效益。这就需使物品的装人次序按pi/wi比值的非增次序来考虑。在这种策略下的量度是已装物品的累计效益值与所用容量之比。其量度标准是每次装入要使累计效益值与所用容量的比值有最多的增加或最少的减小(第二次和以后的装入可能使此比值减小)。将此贪心策略应用于例1的数据,得到解④。如果将物体事先按pi/wi的非增次序分好类,则过程greedy—knaPsack就得出这一策略下背包问题的解。
【算法描述】
procedure greedy-knaPsack(P,w,m,x,n)
real P(1:n),w(1:n),x(1:n),m,cu;//M是背包的容量大小,而x(1:n)是解向量
integer i,n;
Sort(p,w); //按P(i)/wi≥P(i+1)/w(i+1)排序的n件物品的效益值和重量,并且形成新的P(1:n)和w(1;n)。
x<- 0 //将解向量初始化为零"
cu<-m ; //cu是背包剩余容量//
for i<-1 to n do
if w(i)>cu then exit endif
xi <- 1;
cu <- cu-w(i);
repeat
if i≤n then x(i)<-cu/w(i);
endif
end greedy-knaPsack
【测试数据】
测试数据自定,要求物品的个数n,背包总容量M和每种物品的重量值及效益值。在程序运行过程中由用户从键盘输入。
【实现提示】
采用静态数组存储。