给出一个天平的结构,求将一些砝码放入天平的“平衡度”最小
树形的状态压缩的动态规划
预处理比较麻烦,首先枚举出所有状态,每个点的砝码数,以及每种状态对应的砝码总质量,然后进行状态压缩的树形动态规划即可
{
pku3719 Art of Balance
By largelymfs
Accepted 17496K 469MS
Date:2010-05-30 16:32
状态压缩的树形动态规划
}
Program ex;
Const
Infile = 'pku3719.in';
Outfile= 'pku3719.out';
maxn=16;maxs=70000;
Inf = 9999999999999;
Var
state : Array[0..maxn,0..maxs] Of Longint;
count : Array[0..maxn] Of Longint;
weight : Array[0..maxs] Of Longint;
sum, l, r : Array[0..110] Of Longint;
v : Array[0..maxn] of Longint;
opt : Array[0..100, 0..maxs] Of Double;
i, j, t, n, m : Longint;
Procedure Dfs1(num,now, k : longint); //生成每种状态的情况
Begin
if k>16 then Exit;
Dfs1(num, now, k+1);
now := now + 1 shl (k-1);
Inc(count[num+1]);
state[num+1][count[num+1]] := now;
dfs1(num+1, now, k+1);
End;
Procedure Init;
Var
ll, rr, i : Longint;
begin
Readln(n);
For i :=1 To n Do begin
Readln(ll, rr);
l[i] := ll;r[i] := rr;
end;
Readln(m);
For i :=1 To m do read(v[i]);
End;
Procedure getweight; //得到每种状态的重量
var
i, k : longint;
begin
For i := 0 To (1 shl m)-1 Do begin
weight[i] := 0;
For k := 1 To m Do begin
If (1 shl (k-1)) And i<>0 Then Begin
weight[i] := weight[i] + v[k];
end;
end;
end;
End;
Procedure dfs2(k : longint); //得到每个节点下的砝码数
var
ll, rr : longint;
Begin
ll := l[k];rr := r[k];
sum[k] := 0;
If ll>0 then Begin
dfs2(ll);sum[k] := sum[k] + sum[ll];
end;
If rr>0 Then begin
dfs2(rr);sum[k] := sum[k]+sum[rr];
end;
If ll=rr Then Begin
sum[k] := 1;
end;
end;
Procedure getsum;
begin
dfs2(1);
End;
Function get(s : Double) : Double; //取绝对值
begin
if s<0 Then get := -s Else get := s;
end;
procedure getdp(k, s : longint); //进行树形动态规划
Var
ll, i,nowl, nowr, rr : longint;
tmp : Double;
Begin
If opt[k][s]<0 Then begin
opt[k][s] := Inf;
if sum[k]=1 then begin
opt[k][s] := 0;Exit;
end;
ll := l[k];rr := r[k];
For i :=1 To count[sum[ll]] Do begin
nowl := state[sum[ll]][i];
if nowl and s =nowl Then Begin
nowr := s and (not nowl);
getdp(ll, nowl);getdp(rr, nowr);
tmp := opt[ll][nowl]+opt[rr][nowr]+get((weight[nowl]/(weight[nowl]+weight[nowr]))-0.5)*1000;
if tmp<opt[k][s] Then opt[k][s] := tmp;
End;
end;
end;
End;
begin
Assign(Input, Infile);Reset(Input);Assign(output,Outfile);Rewrite(Output);
Readln(t);
Fillchar(count, sizeof(count), 0);
dfs1(0, 0, 1);
While t>0 DO begin
Dec(t);
Init;
getweight;
getsum;
For i := 1 To n do
For j := 0 to (1 shl m)-1 Do
opt[i][j] := -1;
getdp(1, (1 shl m)-1);
writeln(opt[1][(1 shl m)-1]:0:3);
end;
Close(Input);Close(output);
End.