HDU4405 Aeroplane chess (概率DP,转移)

http://acm.hdu.edu.cn/showproblem.php?pid=4405

题意:在一个1×n的格子上掷色子,从0点出发,掷了多少前进几步,同时有些格点直接相连,即若a,b相连,当落到a点时直接飞向b点。求走到n或超出n期望掷色子次数

分析:简单的题目,拿来入门很不错:

如果没有飞机的线 ,这题就是直接 dp[i]+=dp[i+x]/6 +1 了 ; 当前的期望由子期望相加 ; 那航线怎么考虑呢?一开始我以为是加上可以走到点的dp[v] ,可是仔细推敲这是不对了,在注意到航线的转移是不需要价值的,所以直接dp[u]=dp[v] 就好;为什么呢?很简单,例如: 7->8   , 因为8是可以直接由7来的,那8就继承7的期望

#include<bits/stdc++.h>
using namespace std;

vector<int>G[100010];
bool vis[100010];
double dp[100010];
int main()
{
    int n,m;
    while(~scanf("%d%d",&n,&m))
    {
        if(n==0&&m==0) break;
        for(int i=0 ; i<=n ; i++)
        G[i].clear();
        for(int i=0 ; i<m ; i++)
        {
            int u,v;scanf("%d%d",&u,&v);
            G[v].push_back(u);
        }
        memset(dp,0,sizeof(dp));
        memset(vis,0,sizeof(vis));

        for(int i=0 ; i<G[n].size() ; i++)
        {
            int v=G[n][i];
            dp[v]=0;
            vis[v]=1;
        }
        for(int i=n-1 ; i>=0 ; i--)
        {
            if(vis[i]==0){
           for(int x=1 ; x<=6 ; x++)
           {
               dp[i]+=dp[i+x]/6.0;
           }
           dp[i]++;}
           for(int j=0 ; j<G[i].size() ; j++)
           {
               int v=G[i][j];
               dp[v]=dp[i];
               vis[v]=1;
           }
        }
        printf("%.4lf
",dp[0]);
    }
}
View Code
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
using namespace std;
#define N 100010

double dp[N];
int nxt[N];

int main()
{
    int n, m;
    while(~scanf("%d%d", &n, &m), n+m) {
        memset(nxt, -1, sizeof(nxt));
        for(int i = 0; i < m; i++) {
            int u, v;
            scanf("%d%d", &u, &v);
            nxt[u] = v;
        }
        memset(dp, 0, sizeof(dp));
        double dec = (double)1 / 6;
        for(int i = n - 1; i >= 0; i--) {
            if(nxt[i] != -1) {
                dp[i] = dp[nxt[i]]; //如果可以飞,就直接把上一步的值赋给它
                continue;
            }
            for(int j = 1; j <= 6; j++) {
                if(i + j <= n) {
                    dp[i] += dp[i + j] * dec; //不能飞的话,就掷骰子为1-6的概率都为1/6,递推
                }
            }
            dp[i]++; //走到下一步要+1
        }
        printf("%.4f
", dp[0]);
    }
    return 0;
}
View Code
原文地址:https://www.cnblogs.com/shuaihui520/p/10952463.html