终于又一次迎来了一道期望DP题,按照约定,小C把它贴了出来。

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]内的整数。

Solution

  关于概率期望的题目让人头大,但是如果你还记得之前的口诀“概率正着做,期望倒着做”,这题就会变得很无脑。

  很显然这题要我们求的是期望,所以我们倒着开始思考问题。

  我们注意到n的范围小等于15,那还能是什么做法啊,当然是状压啊。

  于是我们考虑设计状态,f[i][j]表示取了已经抛出i次物品,并且取了集合为j的物品至少1次,这之后按照最优策略能取到的期望值。

  所谓最优策略,实际上就是比较转移代价和目标收益之间的大小关系,

  假设我们在状态f[i][j],假设可以取得物品x,我们就要斟酌一下取得x的代价和取得x之后的收益,

  也就是比较-w[x]和f[i+1][j|ys[x]]的大小,

  如果-w[x]<f[i+1][j|ys[x]],也就是说收益更大,按照最优原则我们应该要取;(为什么是“应该”呢)

  反之就是代价更大,按照最优原则我们肯定不能取,但是请注意,不取x也有一个收益,那就是f[i+1][j]。

  不过就算取x的收益比代价大,但这两者的差值不一定大于不取x的收益,所以按照最优策略还是要对两者取一个max。

  结合上面的思路来看,我们发现f[i][j]永远不可能是负数。

  前面说的是能够取得物品x的情况,那么什么时候取不了物品x(未满足x的前提宝物集合)呢?

  这种问题还用问?看看你自己设计的状态就知道了吧。

  转移方程:

  其中如果取不了物品k,用 0 代替。

  时间复杂度,虽然复杂度有5亿然而却跑得飞快。

#include <cstdio>
#include <algorithm>
#include <cstring>
#define MS 17
#define MN 35005
using namespace std;
int ys[MS],w[MS],prt[MS];
double f[][MN];
int m,n,stp; inline int read()
{
int n=,f=; char c=getchar();
while (c<'' || c>'') {if(c=='-')f=-; c=getchar();}
while (c>='' && c<='') {n=n*+c-''; c=getchar();}
return n*f;
} int main()
{
register int i,j,k,x,lg,rg;
m=read(); n=read();
for (ys[]=,i=;i<=n;++i) ys[i]=ys[i-]<<;
stp=ys[n]<<;
for (i=;i<=n;++i)
for (w[i]=read(),x=read();x;x=read()) prt[i]|=ys[x];
for (i=m-,lg=,rg=;i>=;--i,swap(lg,rg))
for (j=;j<stp;f[lg][j++]/=n)
for (f[lg][j]=,k=;k<=n;++k)
f[lg][j]+=max(((j&prt[k])==prt[k])?f[rg][j|ys[k]]+w[k]:,f[rg][j]);
printf("%.6lf",f[rg][]);
}

Last Word

  自己手算一些小数据也是不错的调试技巧。

  为了缩行可能代码画风会有点崩坏。

[BZOJ]1076 奖励关(SCOI2008)的更多相关文章

  1. BZOJ 1076 奖励关 状态压缩DP

    题目链接: https://www.lydsy.com/JudgeOnline/problem.php?id=1076 题目大意: 你正在玩你最喜欢的电子游戏,并且刚刚进入一个奖励关.在这个奖励关里, ...

  2. scoi 2008 && bzoj 1076 奖励关

    传送门:http://www.lydsy.com/JudgeOnline/problem.php?id=3223 思路:15?好,状压,OK. 这是转移方程 if((s[k]&j)==s[k] ...

  3. BZOJ 1076 奖励关

    注意几点: 1.为什么要逆推?由此状态可以轻易算出彼状态是否可行,而彼状态却无法轻易还原为此状态. 2.为什么可以逆推?假设时光倒流了....23333 3.注意位运算的准确,大胆写方程. #incl ...

  4. bzoj 1076 奖励关 状压+期望dp

    因为每次选择都是有后效性的,直接dp肯定不行,所以需要逆推. f[i][j]表示从第i次开始,初始状态为j的期望收益 #include<cstdio> #include<cstrin ...

  5. BZOJ 1076 奖励关(状压期望DP)

    当前得分期望=(上一轮得分期望+这一轮得分)/m dp[i,j]:第i轮拿的物品方案为j的最优得分期望 如果我们正着去做,会出现从不合法状态(比如前i个根本无法达到j这种方案),所以从后向前推 如果当 ...

  6. 【bzoj 1076】【SCOI2008】奖励关

    1076: [SCOI2008]奖励关 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 1602  Solved: 891[Submit][Status ...

  7. 【BZOJ】【1076】【SCOI2008】奖励关

    状压DP+数学期望 蒟蒻不会啊……看题跑…… Orz了一下Hzwer,发现自己现在真是太水了,难道不看题解就一道题也不会捉了吗? 题目数据范围不大……100*(2^16)很容易就跑过去了…… DP的时 ...

  8. 【BZOJ】1076: [SCOI2008]奖励关(状压dp+数学期望)

    http://www.lydsy.com/JudgeOnline/problem.php?id=1076 有时候人蠢还真是蠢.一开始我看不懂期望啊..白书上其实讲得很详细的,什么全概率,全期望(这个压 ...

  9. bzoj 1076: [SCOI2008]奖励关

    Description 你正在玩你最喜欢的电子游戏,并且刚刚进入一个奖励关.在这个奖励关里,系统将依次随机抛出k次宝物,每次你都可以选择吃或者不吃(必须在抛出下一个宝物之前做出选择,且现在决定不吃的宝 ...

随机推荐

  1. HTML5的新的结构元素介绍

    HTML5的新的结构元素介绍 一.HTML5与HTML4的区别 1. 取消了一些过时的HTML4的标签 其中包括纯粹显示效果的标记,如<font>和<center>,它们已经被 ...

  2. 第四十四条:为所有导出的API元素编写文档注释

    简而言之,要为API编写文档,文档注释是最好,最有效的途径.对于所有可导出的API元素来说,使用文档注释应该被看作是强制性的.要 采用一致的风格来遵循标准的约定.记住,在文档注释内部出现任何的HTML ...

  3. 关于移动web教程免费发布

    各位老铁大家好,最近经历了太多太多,精力一直不能集中做自己愿意做的事情. 移动Web课程一开始设置收费10块,其实本意是让大家感觉有支出,就会相对珍惜好好学习,但是发现收费把大部分人挡在门外,现在恢复 ...

  4. C# if判断语句执行顺序

    DataTable dt = null; )//不报错,因为先执行dt != null 成立时才执行dt.Rows.Count > 0 { } && dt != null)//报 ...

  5. JAVA_SE基础——39.继承

    在面向对象程序设计中,可以从已有的类派生出新类. 这称做继承(inheritance). 白话解释: 例子1:继承一般是指晚辈从父辈那里继承财产,也可以说是子女拥有父母给予他们的东西. 例子2:猫和狗 ...

  6. 关于APIcloud对应C#的 wcf框架作为后台,实现多库功能

    首先,我是使用ajax原来的请求方式,并没有使用apicloud中封装的请求方式. 前端代码: function makeRequest() { //alert("inside makeRe ...

  7. 机器学习中 K近邻法(knn)与k-means的区别

    简介 K近邻法(knn)是一种基本的分类与回归方法.k-means是一种简单而有效的聚类方法.虽然两者用途不同.解决的问题不同,但是在算法上有很多相似性,于是将二者放在一起,这样能够更好地对比二者的异 ...

  8. 聊一聊C#的Equals()和GetHashCode()方法

    博客创建一年多,还是第一次写博文,有什么不对的地方还请多多指教. 关于这次写的内容可以说是老生长谈,百度一搜一大堆.大神可自行绕路. 最近在看Jeffrey Richter的CLR Via C#,在看 ...

  9. Spring Security 入门(1-7)Spring Security - Session管理

    参考链接:https://xueliang.org/article/detail/20170302232815082 session 管理 Spring Security 通过 http 元素下的子元 ...

  10. IDE-Android Studio -FAQ-使用习惯(不断更新 欢迎留言)

    摘要: 从ecplise工具切换到android studio后遇到了很多问题,起初亦非常痛苦,城墙内外阅博无数才得以解决.所以把当时遇到的问题记录下来,方便后来人学习. 另如果有遇到未纪录的问题欢迎 ...