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