BZOJ1076奖励关题解

链接

很容易想到状压,f[i][s]表示前i个选择的箱子集合为s的最大期望

果断wa了,因为有一些不合法的状态,譬如f[1][1111001]这样的状态

这样的状态不好排除,所以改用倒推

用f[i][s]表示i-1的选择集合为s的,i到k的最大期望

转移时枚举i处的选择,如果可以选该箱子,则为f[i+1][s|(1<<j)]

如果不选则为f[i+1][s]判断一下可行性然后取max就好了

# include<iostream>
# include<cstdio>
# include<algorithm>
# include<cmath>
# include<cstring>
using namespace std;
const int mn = 105;
double f[mn][1<<15];
int n,k,val[mn],sit[mn];
int main()
{
    scanf("%d%d",&k,&n);
    for(int i=1;i<=n;i++)
    {
        int t;
        scanf("%d%d",&val[i],&t);
        while(t)
        {
            sit[i]+=(1<<(t-1));
            scanf("%d",&t);
        }
    }
    for(int i=k;i>=1;i--)
    {
        for(int j=0;j<(1<<n);j++)
        {
            for(int s=1;s<=n;s++)
                if((sit[s] & j) == sit[s])
                f[i][j]+=max(f[i+1][j],f[i+1][j | (1<<(s-1))]+val[s]);
                else
                    f[i][j]+=f[i+1][j];
            f[i][j]=f[i][j]/(1.0*n);
        }
    }
    printf("%.6lf",f[1][0]);
    return 0;
}

 

posted @ 2018-09-10 19:47 logeadd 阅读(...) 评论(...) 编辑 收藏