Aeroplane chess HDU - 4405 飞行棋问题 期望DP 寒假集训

Hzz loves aeroplane chess very much. The chess map contains N+1 grids labeled from 0 to N. Hzz starts at grid 0. For each step he throws a dice(a dice have six faces with equal probability to face up and the numbers on the faces are 1,2,3,4,5,6). When Hzz is at grid i and the dice number is x, he will moves to grid i+x. Hzz finishes the game when i+x is equal to or greater than N.

There are also M flight lines on the chess map. The i-th flight line can help Hzz fly from grid Xi to Yi (0<Xi<Yi<=N) without throwing the dice. If there is another flight line from Yi, Hzz can take the flight line continuously. It is granted that there is no two or more flight lines start from the same grid.

Please help Hzz calculate the expected dice throwing times to finish the game.
Input
There are multiple test cases.
Each test case contains several lines.
The first line contains two integers N(1≤N≤100000) and M(0≤M≤1000).
Then M lines follow, each line contains two integers Xi,Yi(1≤Xi<Yi≤N).
The input end with N=0, M=0.
Output
For each test case in the input, you should output a line indicating the expected dice throwing times. Output should be rounded to 4 digits after decimal point.
Sample Input
2 0
8 3
2 4
4 5
7 8
0 0
Sample Output
1.1667
2.3441
从期望DP来看,与概率DP相反一般是从后往前递推,所以对每次投掷筛子来说,它的期望是从+1到+6所有期望的平均值+1(包括自己),但是这道题有个飞行航线,可以从一个点直接跳到另一个点,那么我们可以先把这几条航线存到一颗树中,对于每个点,如果有对应的节点,那么这个点会把同一条航线上对应点的期望值DP变成相同值。
然后对这条链的下一个节点进行标记,表示这个点已经传递过不需要再次计算了

#include <stdio.h>
#include <string.h>
#include <math.h>
#include <map>
#include <stack>
#include <set>
#include <queue>
#include <vector>
#include <iostream>
#include <algorithm>
#include <cstring>
#include <string>
#include <cstdio>
#define ls (p<<1)
#define rs (p<<1|1)
//#include<bits/stdc++.h>
using namespace std;
const int maxn=1e6;
bool father[maxn];
double dp[maxn];
int a[maxn],vis[maxn];
vector<int>edge[maxn];
void solve(){
    
    
    int n,m;
    while(scanf("%d%d",&n,&m)!=EOF){
    
    
        if(n==0&&m==0) break;
        for(int i=0;i<=n;i++)
            edge[i].clear();
        memset(vis,0,sizeof(vis));
        for(int i=1;i<=m;i++){
    
    
            int a,b;
            cin>>a>>b;
            edge[b].push_back(a);
            edge[a].push_back(b);
        }
        for(int i=0;i<edge[n].size();i++){
    
    
            vis[edge[n][i]]=1;
        }
        memset(dp,0,sizeof(dp));
        for(int i=n-1;i>=0;i--){
    
    
            if(vis[i]==0){
    
    
                double ans=0;
                for(int j=1;j<=6;j++)
                    ans+=dp[i+j]/6;
                dp[i]=ans+1;
                vis[i]=1;
            }
            for(int j=0;j<edge[i].size();j++){
    
    
                dp[edge[i][j]]=dp[i];
                vis[edge[i][j]]=1;
            }
        }
        printf("%.4lf\n",dp[0]);
    }
}
int main()
{
    
    
    ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
    solve();
    return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_45891413/article/details/112851850