感谢作者:
http://blog.csdn.net/qiqijianglu/article/details/8007941
http://kicd.blog.163.com/blog/static/126961911200910168335852/
Aeroplane chess
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 1067 Accepted Submission(s): 727
There are also M flight lines on the chess map. The i-th flight line can help Hzz fly from grid Xi to Yi (0<Xi<Yi<=N) without throwing the dice. If there is another flight line from Yi, Hzz can take the flight line continuously. It is granted that there is no two or more flight lines start from the same grid.
Please help Hzz calculate the expected dice throwing times to finish the game.
Each test case contains several lines.
The first line contains two integers N(1≤N≤100000) and M(0≤M≤1000).
Then M lines follow, each line contains two integers Xi,Yi(1≤Xi<Yi≤N).
The input end with N=0, M=0.
2 0 8 3 2 4 4 5 7 8 0 0
1.1667 2.3441
#define DeBUG
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <cstdlib>
#include <algorithm>
#include <vector>
#include <stack>
#include <queue>
#include <string>
#include <set>
#include <sstream>
#include <map>
#include <bitset>
using namespace std ;
#define zero {0}
#define INF 2000000000
#define EPS 1e-6
typedef long long LL;
const double PI = acos(-1.0);
//#pragma comment(linker, "/STACK:102400000,102400000")
inline int sgn(double x)
{
return fabs(x) < EPS ? 0 : (x < 0 ? -1 : 1);
}
#define MAXN 100005
int turn[MAXN];
double dp[MAXN];
int main()
{
#ifdef DeBUGs
freopen("//home//amb//桌面//1.in", "r", stdin);
#endif
int N, M;
int x, y;
double temp;
while (scanf("%d%d", &N, &M), N || M)
{
memset(turn, 0, sizeof(turn));
while (M--)
{
scanf("%d%d", &x, &y);
turn[x] = y;
}
dp[N] = 0;
for (int i = N - 1; i >= 0; i--)
{
if (turn[i])
dp[i] = dp[turn[i]];
else
{
dp[i] = 0.0;
for (int j = 1; j < 7; j++)
{
if (j + i <= N)
temp = (dp[j + i] + 1) / 6;
else
temp = 1.0 / 6.0;
dp[i] += temp;
}
}
}
printf("%0.4lf\n", dp[0]);
}
return 0;
}
kicd‘s原文
简说期望类问题的解法
2009-11-16 20:33:05| 分类: 默认分类 |举报 |字号 订阅
近年的acm竞赛中,数学期望问题常有涉及,在以前也常让本人感到很头疼,近来突然开窍,掌握了基本的分析方法,希望对大家有帮助。写得浅薄,可能数学上不够严谨,只供理解。
首先,来看下期望有啥基本的公式。
第二条式子是今天的主角,他表明了期望有线性的性质,简单理解就是期望之间可根据关系,简单运算(不严谨的理解)。这就为我们解决一个期望问题,不断转化为解决另外的期望问题,最终转化到一个已知的期望上。
举一个求期望最简单的例子,见下图。
假设有个人在 1号节点处,每一分钟他会缘着边随机走到一个节点或者在原地停留,问他走到4号节点需要平均几分钟?
这是个简单的期望问题,我们用Ei(i=1,2,3,4)表示从i号节点走到4号节点的数学期望值。根据题意对1号节点有
E1=(1/3)*E1+(1/3)*E2+(1/3)*E3+1①
表示他下一分钟可以走到2或者3或在原地1,每个可能概率是1/3 ,注意是下一分钟,故要加上1.
同理我们对节点2,3同样可以列出
E2=(1/3)*E1+(1/3)*E2+(1/3)*E4+1②
E3=(1/3)*E1+(1/3)*E3+(1/3)*E4+1③
那E4等于多少呢? 很明显E4=0 ④,因为他就是要到点4
这样上面1234式其实就是组成了一组方程组,解方程组就可得出E1!!,用高斯消元,复杂度是O(n^3)
从上述例子,我们可总结出如何解决期望类问题,根据题意,表示出各个状态的期望(上例的Ei,1234),根据概率公式,列出期望之间的方程,解方程即可。
下面看用上述思路如何解决一道题(poj2096)
原题见附件1。
题意简述: 一个人受雇于某公司要找出某个软件的bugs和subcomponents,这个软件一共有n个bugs和s个subcomponents,每次他都能同时随机发现1个bug和1个subcomponent,问他找到所有的bugs和subcomponents的期望次数。
我们用E(i,j)表示他找到了i个bugs和j个subcomponents,离找到n个bugs和s个subcomponents还需要的期望次数,这样要求的就是E(0,0),而E(n,s)=0,对任意的E(i,j),1次查找4种情况,没发现任何新的bugs和subcomponents,发现一个新的bug,发现一个新的subcomponent,同时发现一个新的bug和subcomponent,用概率公式可得:
E(i,j)=1+(i*j/n/s)*E(i,j)+(i*(s-j)/n/s)E(i,j+1)+
((n-i)*j/n/s)*E(i+1,j)+(n-i)*(s-j)/n/s*E(i+1,j+1);
这样根据边界就可解出所有的E(i,j),注意因为当我们找到n个bugs和s个subcomponents就结束,对i>n||j>s均无解的情况,并非期望是0.(数学上常见问题,0和不存在的区别)
那这题是否也是要用高斯消元呢? 用高斯消元得话复杂度是O(n^3),达到10^18 根本是不可解的!!
但其实,注意观察方程,当我们要解E(i,j)的话就需要E(i+1,j),E(I,j+1),E(i+1,j+1), 一开始已知E(n,s),那其实只要我们从高往低一个个解出I,j就可以了! 即可根据递推式解出所有的E(I,j) 复杂度是O(n),10^6 ,完美解决。程序见附件2
从上面这道题,我们再次看到了解决期望问题的思路,而且是用到了递推解决问题,其实可递推的原因,当我们把各个状态当成是一个个节点时,概率关系为有向边,我们可看到,可递推的问题其实就是这个关系图是无环的!!那必须要用方程组解决的问题其实就是存在环!!!! 而且我还要指出的是用高斯消元的时候,要注意误差的问题,最好把式子适当的增大,避免解小数,否则误差太大,估计也会卡题。
本文到此结束,简单讲解了期望类问题的解决思路,更加深入的学习可参考wc2009两篇的论文,希望能帮到大家!!