基本演算法 揹包問題

2021-03-31 08:56:30 字數 3217 閱讀 9249

三、揹包問題

*部分揹包問題可有貪心法求解:計算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]);

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

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

演算法 揹包問題

揹包問題用逆序減少空間複雜度的情況下,揹包問題,如果是多維揹包 質量,容積,個數 則加矩陣維度 如果是01揹包,則逆序內迴圈,如果是完全揹包 每種物品個數不限 則順序內迴圈,如果是混合揹包 限制每種物品的個數 include using namespace std define maxn 110 d...

演算法 揹包問題

什麼是揹包問題呢?就是乙個特定載重的揹包,給你乙個資料表,求解其最優的結果,那麼很顯然嘍 這就是乙個優化問題 那麼我們具體一點!這個揹包載重8千克 李子 4kg 4500元 蘋果 5kg 5700元 士多啤梨 1kg 1100元 橘子 2kg 2250元 甜瓜 6kg 6700元 那,我們使用動態規...