luogu P2473 [SCOI2008]奖励关

传送门

(n)很小,可以想到设(f_{i,j})为第(i)轮,获得的物品集合为(j)的答案,然后顺推

恭喜你很可能会WA,因为这样可能会有些状态无法到达,而难以计算答案

概率期望是可以逆推的,那么(f_{i,j})为第(i)轮及之前获得的物品集合为(j),(i)后面的最大期望得分,转移就枚举每个物品能不能放,以及如果能放会不会放(后者要取max)

最后答案为(f_{1,0})

// luogu-judger-enable-o2
#include<bits/stdc++.h>
#define LL long long
#define il inline
#define re register
#define db double
#define s(i) (1<<(i-1))

using namespace std;
const int N=16,M=(1<<15)+10;
il LL rd()
{
  re LL x=0,w=1;re char ch=0;
  while(ch<'0'||ch>'9') {if(ch=='-') w=-1;ch=getchar();}
  while(ch>='0'&&ch<='9') {x=(x<<3)+(x<<1)+(ch^48);ch=getchar();}
  return x*w;
}
int kk,n,nn,a[N][2];
db f[2][M],inf;

int main()
{
  kk=rd(),n=rd(),nn=1<<n;
  for(int i=1;i<=n;i++)
    {
      a[i][0]=rd();
      while(1)
        {
          int x=rd();
          if(!x) break;
          a[i][1]|=s(x);
        }
    }
  int nw=1,la=0;
  for(int h=kk;h>=1;h--)
    {
      for(int i=0;i<nn;i++)
        {
          f[nw][i]=0;
          for(int j=1;j<=n;j++)
            if((i&a[j][1])==a[j][1]) f[nw][i]+=max(f[la][i|s(j)]+(db)a[j][0],f[la][i])/(db)n;
            else f[nw][i]+=f[la][i]/(db)n;
        }
      nw^=1,la^=1;
    }
  printf("%.6lf
",f[la][0]);
  return 0;
}


原文地址:https://www.cnblogs.com/smyjr/p/9775371.html