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.
原文地址:https://www.cnblogs.com/BLADEVIL/p/3527239.html