HDU 4405-Aeroplane chess(概率dp)

题意:

n+1格飞行棋,编号0-n,从0格开始,每次扔一个色子,得到的点数就向前走几步,但有有些格子到达后可以直接飞到后面的格子,

当到达>=n的地方结束,求结束扔色子的期望次数。

分析:

dp[i]表示i格到结束需要的期望次数,dp[n]-dp[n+5]是0,dp[0]即为所求,先处理直接飞的情况

#include <map>
#include <set>
#include <list>
#include <cmath>
#include <queue>
#include <stack>
#include <cstdio>
#include <vector>
#include <string>
#include <cctype>
#include <complex>
#include <cassert>
#include <utility>
#include <cstring>
#include <cstdlib>
#include <iostream>
#include <algorithm>
using namespace std;
typedef pair<int,int> PII;
typedef long long ll;
#define lson l,m,rt<<1
#define pi acos(-1.0)
#define rson m+1,r,rt<<11
#define All 1,N,1
#define N 100010
#define read freopen("in.txt", "r", stdin)
const ll  INFll = 0x3f3f3f3f3f3f3f3fLL;
const int INF= 0x7ffffff;
const int mod =  1000000007;
double dp[N];
//fly[i]i格可以最终飞到的格子
int fly[N],n,m;
void solve(){
    memset(dp,0,sizeof(dp));
    for(int i=n-1;i>=0;--i){
        if(fly[i]!=-1){
            dp[i]=dp[fly[i]];//可由前面的格子飞过来
        }
        else{
        //6种情况
            for(int j=1;j<=6;++j)
                dp[i]+=dp[i+j]/6.0;
            dp[i]+=1.0;
        }
    }
    printf("%.4lf\n",dp[0]);
}
int main()
{
    while(~scanf("%d%d",&n,&m)){
        if(n==0&&m==0)break;
        memset(fly,-1,sizeof(fly));
        int u,v;
        while(m--){
            scanf("%d%d",&u,&v);
            fly[u]=v;
        }
        for(int i=0;i<=n;++i){
            int j=fly[i];
            if(j==-1)continue;
            while(fly[j]!=-1){
                j=fly[j];
            }
            fly[i]=j;
        }
        solve();
    }
return 0;
}        

 

posted on 2015-08-17 22:06  积跬步、至千里  阅读(163)  评论(0编辑  收藏  举报

导航