洛谷P2473 [SCOI2008]奖励关(期望+状压)

传送门

我数学期望还是太差了……

先考虑状压模型,设$dp[i][S]$表示第$i$轮,当前宝物状态为$S$,能获得的最大期望分数

然而这个模型有一个问题,第$i$轮不一定能达到状态$S$

那么考虑转化一下,$dp[i][S]$表示第$1$至$i-1$轮的宝物状态为$S$,第$i$至$n$轮的期望分数

那么我们就可以倒推了

那么对于第$k$个宝物,可以分为两种情况

1.可以选,那么此时可以选择选或者不选,则$dp[i][S]+=max{dp[i+1][S],dp[i+1][S|(1<<k-1)]+a[k]}$

2.不能选,那么$dp[i][S]+=dp[i+1][S]$

然后因为这玩意儿是一个期望,所以每一次做完之后都得$dp[i][S]/=n$

 1 //minamoto
 2 #include<cstdio>
 3 #define max(a,b) ((a)>(b)?(a):(b))
 4 #define getc() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++)
 5 char buf[1<<21],*p1=buf,*p2=buf;
 6 inline int read(){
 7     #define num ch-'0'
 8     char ch;bool flag=0;int res;
 9     while((ch=getc())>'9'||ch<'0')
10     (ch=='-')&&(flag=true);
11     for(res=num;(ch=getc())<='9'&&ch>='0';res=res*10+num);
12     (flag)&&(res=-res);
13     #undef num
14     return res;
15 }
16 const int N=105;
17 int n,m,sta[17],a[17],S;double dp[N][1<<15];
18 int main(){
19 //    freopen("testdata.in","r",stdin);
20     m=read(),n=read(),S=1<<n;
21     for(int i=1,x;i<=n;++i){
22         a[i]=read();
23         while(x=read()) sta[i]|=1<<x-1;
24     }
25     for(int i=m;i;--i)
26     for(int j=0;j<S;++j){
27         for(int k=1;k<=n;++k){
28             if((j&sta[k])==sta[k]) dp[i][j]+=max(dp[i+1][j],dp[i+1][j|(1<<k-1)]+a[k]);
29             else dp[i][j]+=dp[i+1][j];
30         }
31         dp[i][j]/=n;
32     }
33     printf("%.6lf
",dp[1][0]);
34     return 0;
35 }
原文地址:https://www.cnblogs.com/bztMinamoto/p/9720918.html