HDU 4405 Aeroplane chess(概率dp)

题目链接:HDU 4405 Aeroplane chess

概率dp。

显然终点及终点之后的点的期望都是0。

反着建立了一个有向图,然后从后往前推期望,题目中有一些点可以直接到达下一个点而不用经过摇色子,如果碰见这样的点则必须飞过去而不能正常走。那么这些点如果走过(倒着走过的),就得设置一个标记表示走过了,正常走的时候不走这里。

正常走的时候计算期望就很简单了,dp[i] = 1 + dp[i + 1] * p + dp[i + 2] * p + dp[i + 3] * p + dp[i + 4] * p + dp[i + 5] * p + dp[i + 6] * p,其中p是常量,值为1.0 / 6.0。

#include <iostream>
#include <cstdio>
#include <cstring>

using namespace std;

const int MAX_N = 100000 + 100;
const int MAX_M = 1000 + 10;
const double p = 1.0 / 6.0;

struct Edge
{
    int v, next;
};
Edge e[MAX_M];
int head[MAX_N], vis[MAX_N];
double dp[MAX_N];
int cnt, n, m, a, b;
void addEdge(int u, int v)
{
    e[cnt].v = v;
    e[cnt].next = head[u];
    head[u] = cnt++;
}

int main()
{
    while(scanf("%d%d", &n, &m), n + m)
    {
        memset(vis, 0, sizeof(vis));
        memset(dp, 0, sizeof(dp));
        memset(head, -1, sizeof(head));
        cnt = 0;
        for(int i = 0; i < m; i++)
        {
            scanf("%d%d", &a, &b);
            addEdge(b, a);
        }
        for(int i = head[n]; i != -1; i = e[i].next)
        {
            dp[e[i].v] = 0;
            vis[e[i].v] = 1;
        }
        for(int i = n - 1; i >= 0; i--)
        {
            if(!vis[i])
                dp[i] = 1 + dp[i + 1] * p + dp[i + 2] * p + dp[i + 3] * p + dp[i + 4] * p + dp[i + 5] * p + dp[i + 6] * p;
            for(int j = head[i]; j != -1; j = e[j].next)
            {
                dp[e[j].v] = dp[i];
                vis[e[j].v] = 1;
            }
        }
        printf("%.4lf\n", dp[0]);
    }
    return 0;
}



你可能感兴趣的:(HDU 4405 Aeroplane chess(概率dp))