【总览】

【期望dp】

  求解达到某一目标的期望花费:因为最终的花费无从知晓(不可能从$\infty$推起),所以期望dp需要倒序求解。

  设$f[i][j]$表示在$(i, j)$这个状态实现目标的期望值(相当于是差距是多少)。

首先$f[n][m] = 0$,在目标状态期望值为0。然后$f = (\sum f' × p) + w $,$f'$为上一状态(距离目标更近的那个,倒序),$p$为从$f$转移到$f'$的概率(则从$f'$转移回$f$的概率也为$p$),w为转移的花费。

最后输出初始位置的$f$即可。

特别的,当转移关系不成环时,期望dp可以线性递推。

但当转移关系成环时,期望dp的最终状态相当于一个已知量,而转移关系相当于一个个方程,可以使用【高斯消元】解决。

高斯消元期望dp的例题

【概率dp】

  概率dp通常已知初始的状态, 然后求解最终达到目标的概率,所以概率dp需要顺序求解。

  概率dp相对简单,当前状态只需加上所有上一状态乘上转移概率即可:$f = \sum f'_{i} × p_{i}$

【例题】

【hdu3853】Loops

  简单的期望dp题,设$f[i][j]$表示当前位置到达终点的期望体力,则$f[r][c] = 0$。

  已知每个位置不动、向下、向右的概率。设p0为当前状态下停留的概率,p1为向下的概率,p2为向右的概率,那么就从终点开始逆推:

$$f[i][j] = p0 × f[i][j] + p1 × f[i + 1][j] + p2 × f[i][j +1] + 2$$

  dp强调根据已知推未知,发现等号右边$f[i][j]$正是我们要求的,呢么这就可以构成一个方程了。不过没有那么复杂,因为转移关系不是一个环,只要我们将右边的$f[i][j]$移到左边,再将系数除过去,等号右边就都是已知的了。

【CODE】

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<string>
#include<vector>
#include<algorithm>
#include<cmath>
using namespace std; const int R = , C = ;
const double eps = 1e-;
int r, c;
double p[R][C][];
double f[R][C]; int main(){
while(scanf("%d%d", &r, &c) != EOF){
memset(p, , sizeof p);
memset(f, , sizeof f);
for(int i = ; i <= r; i++)
for(int j = ; j <= c; j++)
scanf("%lf%lf%lf", &p[i][j][], &p[i][j][], &p[i][j][]);
f[r][c] = ;
for(int i = r; i >= ; i--)
for(int j = c; j >= ; j--){
if(i == r && j == c) continue;
if(fabs(1.0 - p[i][j][]) < eps) continue;
f[i][j] = (p[i][j][] * f[i][j + ] + p[i][j][] * f[i + ][j] + 2.0) / (1.0 - p[i][j][]);
}
printf("%.3f\n", f[][]);
}
return ;
}

【hdu4405】AeroplaneChess

  又是一道期望dp。读题可知终点落在$n$~ $n + 5$,将它们的f全部置为$0$。

  因为有直接跳转,所以如果当前点有可以直接跳转到的点,那么这次是不用掷骰子的,因为当前期望等于目标点的期望。

  然后考虑掷色子,摇到$1, 2, 3, 4, , 6$的概率都为$\frac{1}{6}$,所以$f[i] = \sum_{x = 1}^{6} f[i + x] × \frac{1}{6} + 1$

  这样倒序dp便可以得到期望值。

【CODE】

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<string>
#include<vector>
#include<algorithm>
#include<cmath>
using namespace std; const int N = ;
int go[N];
int n, m;
double f[N]; int main(){
while(~scanf("%d%d", &n, &m), n + m){
memset(go, -, sizeof go);
for(int i = ; i <= m; i++){
int x, y; scanf("%d%d", &x, &y);
go[x] = y;
}
memset(f, , sizeof f);
for(int i = n - ; i >= ; i--){
if(go[i] != -){
f[i] = f[go[i]];
continue;
}
f[i] = (f[i + ] + f[i + ] + f[i + ] + f[i + ] + f[i + ] + f[i + ]) / + ;
}
printf("%.4f\n", f[]);
}
return ;
}

【poj2096】收集错误

  这道题很有意思。设$f[i][j]$为收集到$i$种bug,属于$j$个子系统的期望天数,同样$f[n][s] = 0$

  考虑当前bug:

  •  属于已经收集到的$i$种,也属于已经收集到的$j$个系统,概率为$\frac{i × j}{n × s}$
  • 属于已经收集到的$i$种,属于新的一套系统, 概率为$\frac{i × (s - j)}{n × s}$
  • 属于新的一种,属于已经收集到的$j$个系统,概率为$\frac{(n - i) × j}{n × s}$
  • 属于新的一种,属于新的系统,概率为$\frac{(n - i) × (s - j)}{n × s}$

上面顺推求出的概率,应该是等于逆推的概率的。

其余的就很基础了。

【CODE】

#include<iostream>
#include<cstring>
#include<string>
#include<algorithm>
#include<cstdio>
#include<cstdlib>
#include<cmath>
#include<vector>
using namespace std; const int N = , S = ;
double f[N][S];
int n, s; int main(){
scanf("%d%d", &n, &s);
f[n][s] = 0.0;
for(int i = n; i >= ; i--){
for(int j = s; j >= ; j--){
if(n * s - i * j == ) continue;
double c1 = (double)i * ((double)s - (double)j), c2 = ((double)n - (double)i) * (double)j,
c3 = ((double)n - (double)i) * ((double)s - (double)j), c4 = (double)n * (double)s, c5 = (double)n * (double)s - (double)i * (double)j;
f[i][j] = ((c1 * f[i][j + ] + c2 * f[i + ][j] + c3 * f[i + ][j + ] + c4) / c5);
}
}
printf("%.4f\n", f[][]);
return ;
}

【poj3071】FootBall

  终于到概率dp了。设$f[i][j]$表示当前第$i$轮比赛,$j$队获胜的概率,那么他如果想获胜:

  • 首先上一轮比赛他必须获胜。
  • 然后他的对手上一轮必须获胜。
  • 他的对手只能是相邻的。

  判断相邻十分巧妙的使用了二进制:如果把所有队伍的编号都$-1$:

  从$0$开始的自然数(二进制):$0, 1, 10, 11, 100, 101, ......$

  可以发现相邻的数它们的最后一位一定相反。

  进行第一轮比赛后,相当于将相邻俩个节点替换成他们的父节点$(k >> 1)即将最后一位去掉$,此时相邻的点仍然符合规律。

  所以我们判断两队是否能比赛的标准就是:$(j >> (i - 1)) $ ^ $1 == k >> (i - 1)$

【CODE】

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<string>
#include<cmath>
#include<algorithm>
#include<vector>
using namespace std; const int N = ;
int n;
double f[N][], p[][]; int main(){
freopen("h.in", "r", stdin);
while(scanf("%d", &n), n != -){ memset(p, , sizeof p);
memset(f, , sizeof f);
for(int i = ; i <= ( << n); i++){
f[][i] = ;
for(int j = ; j <= ( << n) ; j++)
scanf("%lf", &p[i][j]);
}
for(int i = ; i <= n; i++)
for(int j = ; j <= ( << n); j++)
for(int k = ; k <= ( << n); k++)
if((((j - ) >> (i - )) ^ ) == ((k - ) >> (i - )))
f[i][j] += f[i - ][k] * f[i - ][j] * p[j][k];
double ans = -;
int ret = ;
for(int i = ; i <= ( << n); i++)
if(ans < f[n][i]) ans = max(ans, f[n][i]), ret = i;
printf("%d\n", ret);
}
}

【期望DP】的更多相关文章

  1. 【BZOJ-1419】Red is good 概率期望DP

    1419: Red is good Time Limit: 10 Sec  Memory Limit: 64 MBSubmit: 660  Solved: 257[Submit][Status][Di ...

  2. [NOIP2016]换教室 D1 T3 Floyed+期望DP

    [NOIP2016]换教室 D1 T3 Description 对于刚上大学的牛牛来说, 他面临的第一个问题是如何根据实际情况中情合适的课程. 在可以选择的课程中,有2n节课程安排在n个时间段上.在第 ...

  3. HDU 4336 Card Collector (期望DP+状态压缩 或者 状态压缩+容斥)

    题意:有N(1<=N<=20)张卡片,每包中含有这些卡片的概率,每包至多一张卡片,可能没有卡片.求需要买多少包才能拿到所以的N张卡片,求次数的期望. 析:期望DP,是很容易看出来的,然后由 ...

  4. 【BZOJ-4008】亚瑟王 概率与期望 + DP

    4008: [HNOI2015]亚瑟王 Time Limit: 20 Sec  Memory Limit: 512 MBSec  Special JudgeSubmit: 832  Solved: 5 ...

  5. 期望dp BZOJ3450+BZOJ4318

    BZOJ3450 概率期望DP f[i]表示到i的期望得分,g[i]表示到i的期望长度. 分三种情况转移: ① s[i]=‘x’:f[i]=f[i-1],g[i]=0 ② s[i]=‘o’:f[i]= ...

  6. HDU 4405 期望DP

    期望DP算是第一题吧...虽然巨水但把思路理理清楚总是好的.. 题意:在一个1×n的格子上掷色子,从0点出发,掷了多少前进几步,同时有些格点直接相连,即若a,b相连,当落到a点时直接飞向b点.求走到n ...

  7. POJ 2096 【期望DP】

    题意: 有n种选择,每种选择对应m种状态.每种选择发生的概率相等,每种选择中对应的每种状态发生的概率相等. 求n种选择和m种状态中每种至少发生一次的期望. 期望DP好别扭啊.要用倒推的方法. dp[i ...

  8. ZOJ 3822 Domination 期望dp

    Domination Time Limit: 1 Sec Memory Limit: 256 MB 题目连接 http://acm.zju.edu.cn/onlinejudge/showProblem ...

  9. poj 2096 Collecting Bugs(期望 dp 概率 推导 分类讨论)

    Description Ivan is fond of collecting. Unlike other people who collect post stamps, coins or other ...

  10. uva11600 状压期望dp

    一般的期望dp是, dp[i] = dp[j] * p[j] + 1; 即走到下一步需要1的时间,然后加上 下一步走到目标的期望*这一步走到下一步的概率 这一题,我们将联通分块缩为一个点,因为联通块都 ...

随机推荐

  1. HTML5 jQuery+FormData 异步上传文件,带进度条

    <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <link href ...

  2. RSA加密通信小结(三)--生成加解密所需的SSL命令与流程

    在iOS中使用RSA加密解密,需要用到.der和.p12后缀格式的文件,其中.der格式的文件存放的是公钥(Public key)用于加密,.p12格式的文件存放的是私钥(Private key)用于 ...

  3. 流畅的python学习笔记:第三章

    字典的变种: OrderedDict 首先来看下面的代码,在一个字典中,有name,age,city,在遍历这个字典的时候.顺序却是随机的,不是按照我们添加的顺序也就是name->age-> ...

  4. ecshop商品页增加编辑器fckeditor

    最近在做ecshop的项目,需要在商品单页中增加一项FCKEditor的文本编辑器,但在ecshop的论坛和百度里搜出的方法,试了好几个都没有用,终于找到一个可以正确使用的,和大家分享. ecshop ...

  5. 阿里云OSS存储

    1.accessKeyId 与 accessKeySecret 是由系统分配给用户的,称为ID对,用于标识用户,为访问OSS做签名验证. 2.Bucket是OSS上的命名空间,相当于数据的容器,可以存 ...

  6. XCOM2中敌对生物设计分析(Aliens篇)

    Aliens Aliens作为游戏设定中入侵的外星人,有各式外貌及奇特的战斗方式,掌握一些高能科技或利用精神力量进行攻击 Sectoid 使用灵能战斗的外星人,并无高级版本,初级便会使用精神控制,生命 ...

  7. HTML5+CSS3静态页面项目-PayPaul的总结

    学习前端有一段时间了,一直在看书上的理论知识,而实战项目却很少.师兄常说,想要知道自己的实力有多少,知识掌握了多少,最好的方法就是去实践了,实践出真知嘛.于是决定在这个假期里,主要是通过项目的实践以及 ...

  8. mkdirs自动创建文件夹

    //保存路径 如file路径是E:\filer\a.jpg File toSaveFile=new File("filePath"); if(toSaveFile!=null){ ...

  9. jeecg 弹出框 点击按钮回调父页面 返回值

    jeecg 弹出框 点击按钮回调父页面 返回值 <t:base type="jquery"></t:base> <t:base type=" ...

  10. Web前端总结(小伙伴的)

    以下总结是我工作室的小伙伴的心得,可以参考一下 html+css知识点总结 HTMl+CSS知识点收集 1.letter-spacing和word-spacing的区别 letter-spacing: ...