hdu 4405 飞行棋 概率dp

博客探讨了飞行棋游戏中,从0点出发到达或超过n点摇色子次数的期望值问题。通过概率动态规划方法(f[i])进行分析,其中f[n]=0。文章引用了相关博客资源以帮助理解。

题目:点击打开链接

题意:跳棋有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循环就是一个回带的过程。
题目还有可以直接从a跳到b,不需要投色子的,那样就直接标记一下,a的期望值也就等于b的期望值。(a<b)

#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/



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值