泛化背包
對于背包里最BT的這類題,有優于樹歸的O(C^2)算法:
?????? 對于物品i,枚舉他的兒子s,把f[x]賦予f[s],對兒子進行動歸后,返回利用
?????? f[x,i]=max{f[x,i],f[s,i-a[s]]+w[s]}一次求解
例題:
【題目描述】
聯絡完畢的noip群戰士們,終于等到了集結的號角。他們蜂擁而上,前往與CCF交鋒的戰場。
神龜已經準備好了一輛通往戰場的列車,按照他的計劃,這個列車將能容納最多C個戰士,當然他希望這C個戰士總戰斗力最強。
不幸的是,由于組織者沒有進行合理的秩序安排,戰士們在通往戰場的列車前擠成了一個大堆;由于時間和空間關系,神龜已經無法對戰士按照戰斗力重新列隊,只能從這一堆人中靠前的挑選戰士。
我們可以將noip群戰士們擠成的一個堆抽象成一個樹的模型;樹的根就是列車。一個戰士可以進入列車,當且僅當他到列車上的路徑中的戰士已經全部進入了列車。當然,神龜已經在列車上等待大家了(我們可以認為他,也就是樹根,是0號節點),他可是擁有4千萬戰斗力的勇士呢。
現在請你幫神龜計算,他最多可以帶上多少戰斗力的勇士。
【輸入格式】
第一行包括兩個數n,C,分別代表戰士的總人數和列車上能容納的戰士數。
第2~n+1行每行描述了一個戰士,分別代表該戰士之前的戰士(樹中的父節點)的編號xi,和這個戰士的戰斗力wi。
【輸出格式】
只有一行,列車最多可以帶的勇士的戰斗力之和。
【輸入樣例】
7 5
2 2
0 1
0 4
2 1
7 1
7 6
2 2
?
【輸出樣例】
40000013
?
【數據范圍】
對于20%的數據,1<=n,c<=50;
對于70%的數據,1<=n,c<=500;
對于全部數據,1<=n<=10000,1<=c<=500,0<=xi<=n,0<=wi<=500。
提示:對于已經在車上的神龜,他的戰斗力是常量40000000并且不在數據中出現。
程序:
var
pre,next,w:array[0..10000]of longint;
f:array[0..10000,0..500]of longint;
n,i,j,c:longint;
procedure init;
var
x,y:longint;
begin
fillchar(next,sizeof(next),0);
fillchar(f,sizeof(f),0);
readln(n,c);
for i:=1 to n do
?? begin
???? readln(x,y);
???? pre[i]:=next[x];
???? next[x]:=i;
???? w[i]:=y;
?? end;
end;
procedure dp(x,c:longint);
var
i,j,k,s:longint;
begin
s:=next[x];
while s<>0 do
?? begin
???? f[s]:=f[x];
???? dp(s,c-1);
???? for i:=1 to c do??????????? //由于是二維數組,循環順序不影響
????? if f[x,i]<f[s,i-1]+w[s] then
?????? f[x,i]:=f[s,i-1]+w[s];
???? s:=pre[s];
?? end;
end;
begin
assign(input,'charge.in');assign(output,'charge.out');
reset(input);rewrite(output);
init;
dp(0,c-1);
writeln(f[0,c-1]+40000000);
close(input);close(output);
end.
又短又高效,真是。。。。。
轉載于:https://www.cnblogs.com/SueMiller/archive/2011/06/15/2081700.html
總結
- 上一篇: C#反射读取和设置实体类的属性
- 下一篇: Java那些事之Berkeley DB