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

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. System Request 进入KDB模式过程详解

    0   echo g > /proc/sysrq-trigger   怎么让系统停下来,进入进入KDB循环? 1   需要简单了解下:Linux Magic System Request 2   ...

  2. regsvr32 命令小集注册OCX控件,注册控件(包括十几个举例)

    Regsvr32 进程文件: regsvr32 or regsvr32.exe  进程名称: Microsoft DLL Registration Service  英文描述: regsvr32.ex ...

  3. Android studio导入Eclipse项目,和一些错误的解决

    Android studio导入Eclipse开发的项目步骤如下 如果已经打开Android studio的话就选择你已打开的项目,关闭然后导入 开始导入 导入完成. 2.项目出错 Error:(13 ...

  4. 多个haproxy 之间跳转

    C:\>ping wechatTest.winfae.com 正在 Ping wechatTest.winfae.com [120.55.118.6] 具有 32 字节的数据: 来自 120.5 ...

  5. 编写生成彩色验证码的Servlet

    利用Ajax实现无刷新的彩色验证码时,也需要编写一个名称为PictureCheckCode.java的Servlet,该类继承HttpServlet,主要通过service()方法生成验证码. 下面将 ...

  6. ThinkPHP 自动创建数据、自动验证、自动完成详细例子介绍(十九)

    原文:ThinkPHP 自动创建数据.自动验证.自动完成详细例子介绍(十九) 1:自动创建数据 //$name=$_POST['name']; //$password=$_POST['password ...

  7. C++获取文件大小常用技巧

    C++编程语言在程序开发应用中能够帮助我们轻松的完成许多功能需求.比如今天为大家介绍的C++获取文件大小的方法,就可以以多种方式轻松的实现.现在将会实现方法呈现给大家,以便大家参考. C++获取文件大 ...

  8. POJ 2418 Hardwood Species( AVL-Tree )

    #include <stdio.h> #include <stdlib.h> #include <math.h> #include <string.h> ...

  9. android doGet和doPost

    doGet和doPost的差别 get和post是http协议的两种方法,另外还有head, delete等  这两种方法有本质的差别,get仅仅有一个流,參数附加在url后.大小个数有严格限制且仅仅 ...

  10. hdu1260(dp)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1260 分析:简单dp,dp[i]=min(dp[i-1]+a[i],dp[i-2]); #includ ...