bzoj 1076 状压DP
我们设w[i][s]为当前到第i关,手中的物品为s的时候,期望得分为多少,其中s为二进制表示每种物品是否存在。
那么就比较容易转移了w[i][s]=(w[i-1][s']+v[j]) *(1/k),其中j为枚举当前关可能出现的物品,s‘为s的子集且s’与s只可能相差第j位的物品,且s'包括j物品的所有前提物品,因为每个物品都是随机出现的,所以乘上出现的概率(1/k),因为我们采取的是最优策略,所以对于每个物品的出现我们还需要和w[i-1][s]取一个max,代表这个物品即使我们能取,也可能不取。
/************************************************************** Problem: 1076 User: BLADEVIL Language: Pascal Result: Accepted Time:4340 ms Memory:43588 kb ****************************************************************/ //By BLADEVIL var n, k :longint; a :array[0..20] of longint; need :array[0..20] of longint; w :array[0..110,0..40000] of extended; ans :extended; function max(a,b:extended):extended; begin if a>b then exit(a) else exit(b); end; procedure init; var i :longint; y :longint; begin readln(n,k); for i:=1 to k do begin read(a[i]); y:=1; while y<>0 do begin read(y); if y<>0 then need[i]:=need[i] or 1<<(y-1); end; end; end; procedure main; var i, j, s :longint; begin for i:=n downto 1 do for s:=0 to (1<<k)-1 do for j:=1 to k do if need[j] and s=need[j] then w[i,s]:=w[i,s]+(1/k)*max(w[i+1,s],w[i+1,s or 1<<(j-1)]+a[j]) else w[i,s]:=w[i,s]+(1/k)*w[i+1,s]; writeln(w[1][0]:0:6); end; begin init; main; end.