一直不明白为什么概率是正推,期望是逆推。 现在题目做多了,慢慢好像有点明白了

poj2096

收集bug,  有n个种类的bug,和s个子系统。  每找到一个bug需要一天。

要我我们求找到n个种类的bug,且在每个系统中都找到一个bug的期望天数

设dp[i][j] 为找到i个种类的bug和在j个系统中找到bug后,还需要的期望天数

那么dp[n][s] 肯定是0,而dp[0][0]是我们要求的。 这也就是为什么期望是要逆推。

还有一点就是这一状态的期望会等于   所有(下一状态的的期望*这一状态走向下一状态的概率)的和+1

所有可能的情况如下

找到了一个新种类的bug (n-i)/n 第一维度增加1,在一个已经找到bug的系统里面j/s, 第二维度不增加
找到了一个旧种类的bug i/n 第一维度不增加,在一个没有找到bug的系统里面 (s-j)/s 第二维度增加,
找到了一个新种类的bug (n-i)/n 第一维度增加,在一个没有找到bug的系统里面 (s-j)/s 第二维度增加,
找到了一个旧种类的bug i/n 第一维度不增加 , 在一个已经找到bug的系统里面 j/s 第二维度不增加

所有状态转移方程是

dp[i][j] = (1-i/n)*j/s*dp[i+1][j] + i/n*(1-j/s)*dp[i][j+1] + (1-i/n)*(1-j/s) * dp[i+1][j+1] + i/n*j/s*dp[i][j]    + 1

将红色的部分移到左边化简后得到

dp[i][j] = ((1-i/n)*j/s*dp[i+1][j] + i/n*(1-j/s)*dp[i][j+1] + (1-i/n)*(1-j/s) * dp[i+1][j+1] +1)/(1-i/n*j/s)

 #include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <algorithm>
#include <iostream>
#include <queue>
#include <stack>
#include <vector>
#include <map>
#include <set>
#include <string>
#include <math.h>
using namespace std;
#pragma warning(disable:4996)
#pragma comment(linker, "/STACK:1024000000,1024000000")
typedef long long LL;
const int INF = << ;
/*
double dp[n][s] 表示已经找到n个种类的bug,在s个子系统中都找到了bug的期望天数 找到了一个新种类的bug (n-i)/n 第一维度增加1,在一个已经找到bug的系统里面j/s, 第二维度不增加
找到了一个旧种类的bug i/n 第一维度不增加,在一个没有找到bug的系统里面 (s-j)/s 第二维度增加,
找到了一个新种类的bug (n-i)/n 第一维度增加,在一个没有找到bug的系统里面 (s-j)/s 第二维度增加,
找到了一个旧种类的bug i/n 第一维度不增加 , 在一个已经找到bug的系统里面 j/s 第二维度不增加 dp[i][j] = (1-i/n)*j/s*dp[i+1][j] + i/n*(1-j/s)*dp[i][j+1] + (1-i/n)*(1-j/s) * dp[i+1][j+1] + i/n*j/s*dp[i][j] dp[i][j] = ((1-i/n)*j/s*dp[i+1][j] + i/n*(1-j/s)*dp[i][j+1] + (1-i/n)*(1-j/s) * dp[i+1][j+1] +1)/(1-i/n*j/s) */
double dp[ + ][ + ];
int main()
{ int n, s;
while (scanf("%d%d", &n, &s) != EOF)
{
memset(dp, , sizeof(dp));
dp[n][s] = ;
for (int i = n; i >= ; --i)
{
for (int j = s; j >= ; --j)
{
if (i == n &&j == s)continue;
dp[i][j] += ( - (double)i / n)*j / s*dp[i + ][j] + (double)i / n*( - (double)j / s)*dp[i][j + ] + ( - (double)i / n)*( - (double)j / s)*dp[i + ][j + ] + ;
dp[i][j] /= ( - (double)i / n*j / s);
}
}
printf("%.4lf\n", dp[][]);
}
return ;
}

hdu4405

给我们n+1个格子, 标号0到n,一个人初始在位置0,然后丢骰子向前走,

然后又给定m个 a b , 表示到了位置a,能够到飞到位置b而不需要丢骰子

问走到>=n的位置 需要丢骰子的期望次数

设dp[i] 为从位置i到>=n的位置需要丢骰子的期望次数

dp[i>=n] = 0

dp[i] = 1/6 * dp[i+1] + 1/6*dp[i+2] + ... + 1/6 * dp[i+6]

如果位置i+k  能够飞行, 那么应该用飞行过后的位置的期望带入去算

 #include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <algorithm>
#include <iostream>
#include <queue>
#include <stack>
#include <vector>
#include <map>
#include <set>
#include <string>
#include <math.h>
using namespace std;
#pragma warning(disable:4996)
#pragma comment(linker, "/STACK:1024000000,1024000000")
typedef long long LL;
const int INF = <<;
/*
dp[i>=n] = 0;
dp[i] = dp[i+k] * 1/6
*/
double dp[ + ];
int hs[ + ];
int main()
{
int n, m;
int x, y;
while (scanf("%d%d", &n, &m), n)
{
memset(dp, , sizeof(dp));
memset(hs, , sizeof(hs));
for (int i = ; i < m; ++i)
{
scanf("%d%d", &x, &y);
hs[x] = y;
}
for (int i = n-; i >= ; --i)
{
dp[i] = ;
for (int k = ; k <= ; ++k)
{
if (hs[i + k] != )
{
int t = i + k;
while (hs[t] != )//找到飞行的最终位置, 因为能够多次飞行
{
t = hs[t];
}
dp[i] += dp[t] / ;
}
else
dp[i] += dp[i + k] / ;
}
}
printf("%.4lf\n", dp[]);
}
return ;
}

hdu3853

一个人在迷宫的位置(1,1)  要逃到 迷宫的位置(n,m)

在位置(i,j) 需要2魔力去开启传送阵, 有p1的概率是留在原地, p2的概率往右走,p3的概率往下走

问我们逃到迷宫的位置(n,m)需要的魔力的期望

dp[i][j] = p1 * dp[i][j] + p2*dp[i][j+1]  + p3*dp[i+1][j] + 2

dp[i][j] =  ( p2*dp[i][j+1]  + p3*dp[i+1][j] + 2 ) / (1-p1)

还有一个坑是如果某点停留在原地的概率为1, 这是允许的,   那么肯定所有的点都不会到达这一点,否则答案就会很大,不符合题目所说的

所以应该讲该点的dp[i][j]置为0, 而不应该去计算(万一计算出来很大呢)不然会影响之后的值,  因为虽然走到该点的概率是0, 但是浮点数毕竟有误差。

 #include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <algorithm>
#include <iostream>
#include <queue>
#include <stack>
#include <vector>
#include <map>
#include <set>
#include <string>
#include <math.h>
using namespace std;
#pragma warning(disable:4996)
#pragma comment(linker, "/STACK:1024000000,1024000000")
typedef long long LL;
const int INF = <<;
/*
dp[i][j] = 2 + dp[i][j+1] * p[i][j][1] + dp[i+1][j] * p[i][j][2] + dp[i][j] * p[i][j][0]
dp[i][j] = (2 + dp[i][j+1]*p[i][j][1] + dp[i+1][j] * p[i][j][2])/(1-P[i][j][0]);
*/
const int N = + ;
double p[N][N][];
double dp[N][N];
int main()
{
int n, m;
while (scanf("%d%d", &n, &m) != EOF)
{
for (int i = ; i <= n; ++i)
for (int j = ; j <= m; ++j)
for (int k = ; k < ; ++k)
scanf("%lf", &p[i][j][k]);
dp[n][m] = ;
for (int i = n; i >= ; --i)
{
for (int j = m; j >= ; --j)
{
if (i == n &&j == m)
continue;
if (fabs( - p[i][j][]) <= 1e-)//如果该点停留在原地的概率为1, 这是允许的, 那么肯定所有的点都不会到达这一点,否则答案就会很大,不符合题目所说的
{
dp[i][j] = ;
continue;
}
dp[i][j] = (p[i][j][] * dp[i][j + ] + p[i][j][] * dp[i + ][j]) / ( - p[i][j][]) + /(-p[i][j][]);
}
}
printf("%.3lf\n", dp[][]);
}
return ;
}

期望dp专题的更多相关文章

  1. dp专题训练

    ****************************************************************************************** 动态规划 专题训练 ...

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

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

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

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

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

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

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

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

  6. 期望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]= ...

  7. HDU 4405 期望DP

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

  8. POJ 2096 【期望DP】

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

  9. ZOJ 3822 Domination 期望dp

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

随机推荐

  1. Mahout-Pearson correlation的实现

    计算公式: 并通过以下代码对Mahout in Action的结果进行了验证: 代码例如以下: ` package com.example.mahout; public class TestColl ...

  2. Processing_百度百科

    Processing_百度百科 Processing

  3. LIS小结(O(∩_∩)O~哄哄)

    ~\(≧▽≦)/~啦啦啦,昨天说的是LCS,今天我们要学习的是LIS,什么是LIS呢?  LIS: 最长有序子序列(递增/递减/非递增/非递减)这么说还是有些模糊,举个例子: 在一个无序的序列a1,a ...

  4. hibernate学习(二)

    hibernate 单向一对多映射 一.数据表设计 数据库名:hibernate5 数据表: ①表名:CUSTOMERS 字段: CUSTOMER_ID  CUSTOMER_NAME ②表名:ORDE ...

  5. NET MVC RazorEngine 解析模板生成静态页

    ASP.NET MVC 解析模板生成静态页一(RazorEngine) 简述 Razor是ASP.NET MVC 3中新加入的技术,以作为ASPX引擎的一个新的替代项.在早期的MVC版本中默认使用的是 ...

  6. ORACLE常用数据库类型(转)

    oracle常用数据类型 1.Char 定长格式字符串,在数据库中存储时不足位数填补空格,它的声明方式如下CHAR(L),L为字符串长度,缺省为1,作为变量最大32767个字符,作为数据存储在ORAC ...

  7. Git中的merge命令实现和工作方式

    想象一下有例如以下情形:代码库中存在两个分支,而且每一个分支都进行了改动.最后你想要将当中的一个分支合并到其它的分支中.个人博客网址 http://swinghu.github.com/ 那么要问合并 ...

  8. 安卓开发28:自定义View类

    自定义View类 通过自定义View类,可以自定义复杂的,按照自己需求的控件. 一个简单的例子 mainActivity.java 这个里面就是最普通的代码,但是给自定义的控件加上了一个onclick ...

  9. hdu 4274 Spy&#39;s Work(水题)

    Spy's Work Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total ...

  10. VS快捷键教程

    删除或剪切一行(Ctrl + X) 不须要选择不论什么文本, 用来剪切一行, 最经常使用来删除一行.  删除一行也能用 Shift+Delete 格式化整个文档(Ctrl + K, Ctrl + D) ...