$[SCOI2008]$奖励关

\([SCOI2008]\)奖励关

考虑状压\(DP\),显然设状态为\(f[i][S]\)表示所取集合为\(S\),到第\(i\)轮时的期望。

然后写方程。。。

不对,有点难写。。。

仔细考虑一下,我们会发现实因为我们求的是期望,要知道一个状态从哪些状态转移过来。

但是这样设状态并不能方便的求出。

\(f[i][S]\)为前\(i\)轮所取集合为\(S\),第\(i\)到第\(K\)轮的答案。

倒退即可。

#include<bits/stdc++.h>
using namespace std;
inline int read()
{
    int f=1,w=0;char x=0;
    while(x<'0'||x>'9') {if(x=='-') f=-1; x=getchar();}
    while(x!=EOF&&x>='0'&&x<='9') {w=(w<<3)+(w<<1)+(x^48);x=getchar();}
    return w*f;
}
const int N=20;
const int M=110;
int n,K,Las[N],P[N];
double f[M][1<<N],ans;
int main(){
#ifndef ONLINE_JUDGE
    freopen("A.in","r",stdin);
#endif
    K=read(),n=read();
    for(register int i=1;i<=n;++i)
    {
        P[i]=read();register int x=read();
        while(x) Las[i]|=(1<<(x-1)),x=read();
    }
    for(register int i=K;i>=1;--i)
        for(register int S=0;S<(1<<n);++S)
        {
            for(register int j=1;j<=n;++j)
                if((S|Las[j])!=S) f[i][S]+=f[i+1][S];
                else f[i][S]+=max(f[i+1][S],f[i+1][S|(1<<(j-1))]+P[j]);
            f[i][S]/=n;
        }
    printf("%.6lf",f[1][0]);
}

猜你喜欢

转载自www.cnblogs.com/wo-shi-zhen-de-cai/p/11743540.html
今日推荐