题目:点击打开链接
题意:跳棋有0~n个格子,每个格子X可以摇一次色子,色子有六面p(1=<p<=6),概率相等,可以走到X+p的位置,有些格子不需要摇色子就可以直接飞过去。问从0出发到达n或超过n摇色子的次数的期望。
分析:
f[i]表示从i点到n+点的期望,易见f[n]=0,
比如n=3,m=0
所列方程为e[0]=1/6e[1]+1/6e[2]+1/6e[3]+1
e[1]=1/6e[2]+1/6e[3]+1
e[2]=1/6e[3]+1
e[3]=0
从0这个点可以到1,2,3,4,5,6这几个位置,由于大于等于3游戏结束,不会再有期望的投色子次数了,所以跳到3和大于3的格子里期望值也就都是0了。
所以我们列出n个方程后直接回带就能把e[0]求出来。如e[3]=0可以求出e[2]=1,已知了e[2]和e[3]就可以求出e[1],进而求出e[0].
两层for循环就是一个回带的过程。
#include <cstdio>
#include <cstring>
#include <vector>
#include <algorithm>
#include <map>
#include <string>
#include <iostream>
#include <cmath>
using namespace std;
const int N=100005;
int jump[N];
double f[N];
int main()
{
int n,m;
while(~scanf("%d%d",&n,&m)&&(n+m)){
memset(f,0,sizeof(f));
memset(jump,-1,sizeof(jump));
for(int i=0;i<m;i++){
int a,b;
scanf("%d%d",&a,&b);
jump[a]=b;
}
for(int i=n-1;i>=0;i--){
if(jump[i]!=-1){
f[i]=f[jump[i]];
}
else{
for(int j=1;j<=6;j++){
if(i+j>=n)break;
//if(i+j>=n)f[i]+=(1.0/6)*f[n];
else f[i]+=(1.0/6)*f[i+j];
}
f[i]+=1.0;
}
}
printf("%.4lf\n",f[0]);
}
return 0;
}
以上分析中的举例来自博客:http://www.cnblogs.com/jackge/archive/2013/05/21/3091924.html
不错的博客:http://kicd.blog.163.com/blog/static/126961911200910168335852/
博客探讨了飞行棋游戏中,从0点出发到达或超过n点摇色子次数的期望值问题。通过概率动态规划方法(f[i])进行分析,其中f[n]=0。文章引用了相关博客资源以帮助理解。

630

被折叠的 条评论
为什么被折叠?



