经典的背包问题,知道的麻烦进来看一下.

来源:百度知道 编辑:UC知道 时间:2024/05/10 18:49:28
2.0/1背包

一个旅行者有一个最多能用m公斤的背包,现在有n件物品,它们的重量分别是W1,W2,...,Wn,它们的价值分别为C1,C2,...,Cn.若每种物品只有一件求旅行者能获得最大总价值。

<1>分析说明:

显然这个题可用深度优先方法对每件物品进行枚举(选或不选用0,1控制).

程序简单,但是当n的值很大的时候不能满足时间要求,时间复杂度为O(2n)。按递归的思想我们可以把问题分解为子问题,使用递归函数

设 f(i,x)表示前i件物品,总重量不超过x的最优价值

则 f(i,x)=max(f(i-1,x-W[i])+C[i],f(i-1,x))

f(n,m)即为最优解,边界条件为f(0,x)=0 ,f(i,0)=0;

动态规划方法(顺推法)程序如下:

程序如下:

program knapsack02;
const maxm=200;maxn=30;
type ar=array[1..maxn] of integer;
var m,n,j,i:integer;
c,w:ar;
f:array[0..maxn,0..maxm] of integer;
function max(x,y:integer):integer;
begin
if x>y then max:=x else max:=y;
end;
begin
readln(m,n);
for i:= 1 to n do
readln(w[i],c[i]);
for i:=1 to m do f(0,i):=0;
for i:=1 to n do f(i,0):=0;

for i:=1 to n do
for j:=1 to m do
begin
if j>=w[i] th

一位数组指的是状态模拟
定义一个数组a:array[0..m]of longint;
然后a[i]表示,当背包内装了i公斤的物品时,最大能装下的价值。
主要程序段为:
a[0]:=0;
for i:=1 to n do
for j:=m downto 0 do
if (a[j]>0) and (j+w[i]<=m) then
a[j+w[i]]:=max(a[j+w[i]],a[j]+c[i]);
然后for i:=0 to m do
找出a中的最大值即可
for j:=m downto 0 do是为了防止重复计算
比如有个东东,2公斤
那么a[2],a[4],a[6]……都会计算
而题目中只能取一次,所以才用downto

具体的,最好用读程序写结果的方法去试一次,一目了然
(注:数组清空可以用
fillchar(f,sizeof(f),0);)