zoukankan      html  css  js  c++  java
  • 【SCOI2008】奖励关 题解(状压DP+期望)

    题目链接

    题目大意:给定$n$个宝物,每次随机抛出一个宝物,奖励分数为$p_i$。但如果选这个宝物必须选过它的前置宝物集合。共进行$K$轮问最优策略下的期望。

    $nleq 15,-10^6leq p_ileq 10^6$

    --------------------------

    看到数据范围,状压很容易想到。

    设$f[i][j]$表示到了第$i$轮,宝物取舍状态为$j$的最大期望得分。

    但这样表示有一个问题:可能在第$i$轮没法到达状态$j$。我们无法预知未来。

    改一下定义:$f[i][j]$表示第$1$轮到第$i-1$轮宝物取舍状态为$j$,第$i$轮到第$K$轮的最大期望得分。有如下状态转移方程:

    如果前置宝物都已经取过,那么有$f[i][j]+=max(f[i+1][j],f[i+1][j|(1<<(k-1))]+p[k])$

    如果没有,则直接继承先前状态:$f[i][j]+=f[i+1][j]$。

    最后再除$n$即为期望值。

    代码:

    #include<bits/stdc++.h>
    using namespace std;
    int n,K,p[16],s[16],x;
    double f[105][1<<16];
    inline int read()
    {
        int x=0,f=1;char ch=getchar();
        while(!isdigit(ch)){if (ch=='-') f=-1;ch=getchar();}
        while(isdigit(ch)){x=x*10+ch-'0';ch=getchar();}
        return x*f;
    }
    int main()
    {
        K=read(),n=read();
        for (int i=1;i<=n;i++)
        {
            p[i]=read();
            while(x=read()) s[i]=s[i]|(1<<x-1); 
        }
        for (int i=K;i>=1;i--)
            for (int j=0;j<(1<<n);j++)
            {
                for (int k=1;k<=n;k++)
                    if ((j&s[k])==s[k]) f[i][j]+=max(f[i+1][j],f[i+1][j|(1<<k-1)]+p[k]);
                    else f[i][j]+=f[i+1][j];
                f[i][j]/=n; 
            }
        printf("%lf",f[1][0]);
        return 0;
    }
  • 相关阅读:
    UnitTest 用法
    冒泡排序,快速排序
    Mysql 基础用法
    测试用例的设计方法
    测试分类
    测试模型
    软件开发模型
    day24作业
    day24
    spring常见错误之一个或多个筛选器启动失败。完整的详细信息将在相应的容器日志文件中找到
  • 原文地址:https://www.cnblogs.com/Invictus-Ocean/p/13288024.html
Copyright © 2011-2022 走看看