• 【BZOJ】1076 [SCOI2008]奖励关 期望DP+状压DP


    【题意】n种宝物,k关游戏,每关游戏给出一种宝物,可捡可不捡。每种宝物有一个价值(有负数)。每个宝物有前提宝物列表,必须在前面的关卡取得列表宝物才能捡起这个宝物,求期望收益。k<=100,n<=15。

    【算法】期望DP+状压DP

    【题解】主要需要记录的状态是前缀已有宝物,所以设f[i][S]表示前i关已有宝物列表S的期望收益。

    根据全期望公式,依赖于第i+1关的宝物选择:(如果列表符合)

    $$f[i][S]=sum_{i=1}^{n}frac{1}{n}*Max(f[i+1][S'],f[i+1][S]) , S'=S|(1<<(i-1))$$

    倒推是因为已知前缀列表S的情况下,很容易判断下一关宝物是否可捡。

    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    using namespace std;
    const int inf=100000;
    int a[20],n,m,v[20];
    double f[200][70000];
    int main()
    {
        scanf("%d%d",&n,&m);
        for(int i=1;i<=m;i++)
        {
            scanf("%d",&v[i]);
            int u;scanf("%d",&u);
            a[i]=0;
            while(u!=0)
            {
                a[i]|=(1<<(u-1));
                scanf("%d",&u);
            }
        }
        int maxe=(1<<m)-1;
        for(int i=n-1;i>=0;i--)
        {
            for(int j=0;j<=maxe;j++)
            {
                f[i][j]=0;
                for(int k=1;k<=m;k++)
                {
                    if((a[k]&j)==a[k])f[i][j]+=max(f[i+1][j],f[i+1][j|(1<<(k-1))]+v[k]);
                    else f[i][j]+=f[i+1][j];
                }
                f[i][j]/=m;
            }
        }
        printf("%.6lf",f[0][0]);
        return 0;
    }
    View Code
  • 相关阅读:
    【原创】【JNI】OPUS压缩与解压的JNI调用(.DLL版本)
    线性基学习笔记
    杜教筛&Min_25筛学习笔记
    LOJ2540 随机算法
    仙人掌&圆方树学习笔记
    CF487E Tourists
    BZOJ2125 最短路
    [SHOI2008]仙人掌图
    BZOJ4316 小C的独立集
    NOI2015 品酒大会
  • 原文地址:https://www.cnblogs.com/onioncyc/p/7220082.html
Copyright © 2020-2023  润新知