HDU 4405 期望DP

HDU 4405
题目链接:
http://acm.hdu.edu.cn/showproblem.php?pid=4405
题意:
一个飞行棋类似游戏,每次掷一个骰子,可以向前走1-6步。
存在一些点可以直接飞向一个坐标一定比他大的点V,并且飞到下一个点V后,如果V仍能飞向一个比V大的点W,则继续飞向W。
问掷骰子的期望,使得坐标大于等于n。
思路:
期望DP。
设dp[i]为i到n的期望步数,dp[i] = (dp[i+1]+dp[i+2]+dp[i+3]+dp[i+4]+dp[i+5])/6+1,表示可以走到后面6个点。
输出dp[0]。
WA了几发由于存的方式不太一样。假设(u,v)是一条直飞线,第一次的时候存了air[v] = u,来直接遍历前面。然而根据题目意思,可以有多个点到达v,但是从u出发的就一个点。
源码:

#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <iostream>
#include <string>
using namespace std;
const int MAXN = 1000000 + 5;
double dp[MAXN];
int air[MAXN];
int main()
{
// freopen("1006.in", "r", stdin);
    int n, m;
    while(scanf("%d%d", &n, &m) != EOF && n + m){
        for(int i = 0 ; i <= n + 6; i++)
            air[i] = i, dp[i] = -1.0;
        int u, v;
        for(int i = 0 ; i < m ; i++)
            scanf("%d%d", &u, &v), air[u] = v;
        for(int i = n ; i <= n + 6 ; i++)
            dp[i] = 0;
        for(int i = n; i >= 0 ; i--){
            if(air[i] != i){
                dp[i] = dp[air[i]];
                continue;
            }
            if(dp[i] == -1){
                dp[i] = 0;
                for(int j = i + 1 ; j <= i + 6 ; j++)
                    dp[i] += dp[j];
                dp[i] = dp[i] / 6.0 + 1;
// dp[i]++;
            }
            dp[air[i]] = dp[i];
        }
// printf("dp\n");
// for(int i = 0 ; i <= 50 ; i++)
// printf("dp[%d] = %f\n", i, dp[i]);
// printf("dp\n");
        printf("%.4f\n", dp[0]);
    }
    return 0;
}

你可能感兴趣的:(HDU 4405 期望DP)