C C 演算法例項(三) 揹包問題

2021-06-06 20:48:45 字數 3428 閱讀 4637

*

部分揹包問題可有貪心法求解:計算

pi/wi

資料結構:

w[i]:第i

個揹包的重量;

p[i]:第i

個揹包的價值;1.

0-1揹包:

每個揹包只能使用一次或有限次

(可轉化為一次):

a.求最多可放入的重量。

noip2001

裝箱問題

有乙個箱子容量為

v(正整數,

o≤v≤20000)

,同時有

n個物品

(o≤n≤30)

,每個物品有乙個體積

(正整數

)。要求從

n 個物品中,任取若千個裝入箱內,使箱子的剩餘空間為最小。

l 搜尋方法

procedure search(k,v:integer);

var i,j:integer;

begin

if v=best then exit;

if k<=n then begin

if v>w[k] then search(k+1,v-w[k]);

search(k+1,v);

end;

end;

l dp

f[i,j]為前i

個物品中選擇若干個放入使其體積正好為

j的標誌,為布林型。實現:

將最優化問題轉化為判定性問題

f [i, j] = f [ i-1, j-w[i] ] (w[i]<=j<=v)

邊界:f[0,0]:=true.

for i:=1 to n do

for j:=w[i] to v do f[i,j]:=f[i-1,j-w[i]];

優化:當前狀態只與前一階段狀態有關,可降至一維。

f[0]:=true;

for i:=1 to n do begin

f1:=f;

for j:=w[i] to v do

if f[j-w[i]] then f1[j]:=true;

f:=f1;

end;

b.求可以放入的最大價值。

f[i,j]

為容量為

i時取前

j個揹包所能獲得的最大價值。

f [i,j] = max

c.求恰好裝滿的情況數。

dp:procedure update;

var j,k:integer;

begin

c:=a;

for j:=0 to n do

if a[j]>0 then

if j+now<=n then inc(c[j+now],a[j]);

a:=c;

end;

2.可重複揹包

a求最多可放入的重量。

f[i,j]為前i

個物品中選擇若干個放入使其體積正好為

j的標誌,為布林型。

狀態轉移方程為

f[i,j] = f [ i-1, j – w[i]*k ] (k=1.. j div w[i])

b.求可以放入的最大價值。

usaco 1.2 score inflation

進行一次競賽,總時間

t固定,有若干種可選擇的題目,每種題目可選入的數量不限,每種題目有乙個

ti(解答此題所需的時間)和乙個

si(解答此題所得的分數),現要選擇若干題目,使解這些題的總時間在

t以內的前提下,所得的總分最大,求最大的得分。

*易想到:

f[i,j] = max (0<=k<= i div w[j])

其中f[i,j]

表示容量為

i時取前

j種揹包所能達到的最大值。

*實現:

begin

fillchar(f,sizeof(f),0);

for i:=1 to m do

for j:=1 to n do

if i-problem[j].time>=0 then

begin

t:=problem[j].point+f[i-problem[j].time];

if t>f[i] then f[i]:=t;

end;

writeln(f[m]);

end.

c.求恰好裝滿的情況數。

ahoi2001 problem2

求自然數

n本質不同的質數和的表示式的數目。

思路一,生成每個質數的係數的排列,在一一測試,這是通法。

procedure try(dep:integer);

var i,j:integer;

begin

cal;

if now>n then exit;

if dep=l+1 then begin

cal;

if now=n then inc(tot);

exit;

end;

for i:=0 to n div pr[dep] do begin

xs[dep]:=i;

try(dep+1);

xs[dep]:=0;

end;

end;

思路二,遞迴搜尋效率較高

procedure try(dep,rest:integer);

var i,j,x:integer;

begin

if (rest<=0) or (dep=l+1) then begin

if rest=0 then inc(tot);

exit;

end;

for i:=0 to rest div pr[dep] do

try(dep+1,rest-pr[dep]*i);

end;

思路三:可使用動態規劃求解

usaco1.2 money system

v個物品,揹包容量為

n,求放法總數。

轉移方程:

procedure update;

var j,k:integer;

begin

c:=a;

for j:=0 to n do

if a[j]>0 then

for k:=1 to n div now do

if j+now*k<=n then inc(c[j+now*k],a[j]);

a:=c;

end;

begin

read(now);

i:=0;

while i<=n do begin

a[i]:=1; inc(i,now); end;

for i:=2 to v do

begin

read(now);

update;

end;

writeln(a[n]);

0 1揹包問題(c c )

問題介紹 現在有乙個可以載重w的揹包和n個物品,每個物品的重量和 分別為wi 和vi 請選擇所裝物品,使得在不超過揹包載重的前提下,揹包裡的物品 最高。include include using namespace std w 揹包最大載重 n 物品總數 ws 物品重量 vs 物品價值 res i ...

0 1揹包問題 演算法概論 c c 實現

給定n種物品和一揹包。物品i的重量是wi,其價值為vi,揹包的容量為w 假定物品重量與揹包容量值均為整數 應如何選擇裝入揹包中的物品,使得裝入揹包中物品的總價值最大?設計乙個動態規劃演算法,求解揹包問題。利用動態規劃實現 1 定義子問題 首先考慮引數的確定,在揹包問題中,有關引數有 第i件物品以及加...

演算法(揹包問題 01揹包問題)

01揹包問題 有 n 件物品和乙個容量是 v 的揹包。每件物品只能使用一次。第 i 件物品的體積是 vi,價值是 wi。求解將哪些物品裝入揹包,可使這些物品的總體積不超過揹包容量,且總價值最大。輸出最大價值。輸入格式 第一行兩個整數,n,v,用空格隔開,分別表示物品數量和揹包容積。接下來有 n 行,...