zoukankan      html  css  js  c++  java
  • 【bzoj1076】【SCOI2008】【奖励关】期望最优值dp

    这里写图片描述
    [pixiv] https://www.pixiv.net/member_illust.php?mode=medium&illust_id=60582219

    Description
      你正在玩你最喜欢的电子游戏,并且刚刚进入一个奖励关。在这个奖励关里,系统将依次随机抛出k次宝物,
    每次你都可以选择吃或者不吃(必须在抛出下一个宝物之前做出选择,且现在决定不吃的宝物以后也不能再吃)。
    宝物一共有n种,系统每次抛出这n种宝物的概率都相同且相互独立。也就是说,即使前k-1次系统都抛出宝物1(
    这种情况是有可能出现的,尽管概率非常小),第k次抛出各个宝物的概率依然均为1/n。 获取第i种宝物将得到Pi
    分,但并不是每种宝物都是可以随意获取的。第i种宝物有一个前提宝物集合Si。只有当Si中所有宝物都至少吃过
    一次,才能吃第i种宝物(如果系统抛出了一个目前不能吃的宝物,相当于白白的损失了一次机会)。注意,Pi可
    以是负数,但如果它是很多高分宝物的前提,损失短期利益而吃掉这个负分宝物将获得更大的长期利益。 假设你
    采取最优策略,平均情况你一共能在奖励关得到多少分值?
    Input
      第一行为两个正整数k和n,即宝物的数量和种类。以下n行分别描述一种宝物,其中第一个整数代表分值,随
    后的整数依次代表该宝物的各个前提宝物(各宝物编号为1到n),以0结尾。
    Output
      输出一个实数,保留六位小数,即在最优策略下平均情况的得分。
    Sample Input
    1 2
    1 0
    2 0
    Sample Output
    1.500000
    HINT
    【数据规模】
    1<=k<=100,1<=n<=15,分值为[-10^6,10^6]内的整数。

    最近学期望dp,发现自己功力还不够深厚啊。。。状态转移只想得比较大概,没有真正的想清楚。

    数据范围:状压

    看到题目中的“损失短期利益获得更大利益”,就想到了dp。我们设dp[i][s]表示第i次获得的宝物状态为s的期望最大收益。
    最开始想到的顺推:
    dp[i][s]=max{(dp[i-1][s^(1<<(j-1)]+w[j])*1/n,dp[i-1][s]*1/n}
    其中s^(1<<(j-1))需要是s的合法前继状态。而且丢出的宝物我们不一定要吃。

    不太明白网上为什么说要倒推。大概是因为可以直接由合法状态转移过来,而正推需要判断更多的不合法状态。此时的dp应定义为期望还可以获得的分数。

    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    using namespace std;
    
    const double oo=0x7fffffff;
    
    int pre[20];
    int k,n;
    double scr[20],dp[105][1<<15];
    
    int main(){
        scanf("%d%d",&k,&n);
        for(int i=1;i<=n;i++){
            scanf("%lf",&scr[i]);
            int tmp=0,j;
            while(scanf("%d",&j)){
                if(j==0) break;
                tmp|=(1<<(j-1));
            }
            pre[i]=tmp;
        }
        for(int i=k;i>=1;i--){
            for(int j=0;j<(1<<n);j++){
                for(int q=1;q<=n;q++){
                    if((pre[q]|j)==j){
                        dp[i][j]+=max(dp[i+1][j],dp[i+1][j|(1<<(q-1))]+scr[q]);
                    }
                    else dp[i][j]+=dp[i+1][j];
                }
                dp[i][j]/=(double)n;
            }
        }
        printf("%.6lf
    ",dp[1][0]);
        return 0;
    }
  • 相关阅读:
    Android 最简单的基于FFmpeg的移动端例子:Android HelloWorld
    实现简易的android 直播技术
    Android Service和Thread的关系
    Android Fragment 你应该知道的一切
    SQLyog普通版与SQLyog企业版对比分析
    Sqoop异常解决ERROR tool.ImportTool: Encountered IOException running import job: java.io.IOException: No columns to generate for ClassWriter问题
    SQLyog软件里无法插入中文(即由默认的latin1改成UTF8编码格式)
    Sqoop-1.4.6工具import和export使用详解(官网)
    Sqoop Export原理和详细流程讲解
    Sqoop Import原理和详细流程讲解
  • 原文地址:https://www.cnblogs.com/LinnBlanc/p/7763130.html
Copyright © 2011-2022 走看看