• BZOJ 1076: [SCOI2008]奖励关 [DP 期望 状压]


    传送门

    题意:$n$种宝物,出现$k$次每次一种,每种宝物有价值和吃掉它之前必须要吃掉的宝物的集合,求采取最优策略的期望最大价值

    1<=k<=100,1<=n<=15,分值为[-10^6,10^6]内的整数。


    看到$n$应该想到状压....

    $f[i][s]$表示前$i$次已经吃掉的集合为$s$的期望最大值

    然而正推的话,答案是谁呢?

    所以倒推,表示这个状态到结束得到的期望最大值

    转移枚举出现的宝物,最后乘上概率$frac{1}{n}$

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #include <cmath>
    using namespace std;
    typedef long long ll;
    const int N=105,S=1<<15;
    inline int read(){
        char c=getchar();int x=0,f=1;
        while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
        while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();}
        return x*f;
    }
    int m,n,val[N],need[N];
    double f[N][S];
    int main(){
        freopen("in","r",stdin);
        m=read();n=read();
        for(int i=0;i<n;i++){
            val[i]=read();int x=read();
            while(x) need[i]|=(1<<(x-1)),x=read();
        }
        int All=1<<n;
        for(int i=m;i>=1;i--)
            for(int s=0;s<All;s++){
                for(int j=0;j<n;j++){
                    if((s&need[j])==need[j]) f[i][s]+=max(f[i+1][s],f[i+1][s|(1<<j)]+val[j]); 
                    else f[i][s]+=f[i+1][s];
                }
                f[i][s]/=n;
            }
        printf("%.6lf",f[1][0]);
    }
  • 相关阅读:
    DcotrineFixtureBundle学习
    php方法(1)
    学习笔记(2)
    微信access_token的获取
    学习笔记(1)
    与你相遇——博客园
    单例模式
    Java集合
    sql 优化
    缓存与数据库的数据一致性的解决方案(转)
  • 原文地址:https://www.cnblogs.com/candy99/p/6505832.html
Copyright © 2020-2023  润新知