1. 程式人生 > >【HDU4405】Aeroplane chess(概率dp)

【HDU4405】Aeroplane chess(概率dp)

題目連結

Aeroplane chess

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 6278    Accepted Submission(s): 3901


 

Problem Description

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

 

【題意】

在編號為0-n的格子中下飛行棋?!起點為0終點為n,買擲一次骰子可以前進相應步數,有的位置可以直接飛到另一個位置,計算走到n點的擲骰子的期望次數。

【解題思路】

期望....給跪qaq感覺是世界上最噁心的東西之一,但是再噁心還是得做不是嗎。

設dp[i]為到i點的期望次數,首先要清楚在n這個點因為已經到達終點,所以不用再擲骰子了,期望是0,那麼dp[n]=0,既然已經知道最後一個點的期望,那麼就可以從前往後推,問題就轉換成了求dp[0]的期望。

因為i這個狀態要轉換成下一個狀態可以擲骰子1-6,每擲一次篩子有1/6的可能,所以最終期望就是每次的步數*概率之和。別忘了最後得加1,因為從當前狀態轉換成下一個狀態需要擲一次篩子。

【程式碼】

#include<bits/stdc++.h>
using namespace std;
const int maxn=1e5+5;
int to[maxn];
double dp[maxn];
int main()
{
    int n,m;
    while(~scanf("%d%d",&n,&m) && n || m)
    {
        memset(dp,0,sizeof(dp));
        memset(to,0,sizeof(to));
        while(m--)
        {
            int x,y;
            scanf("%d%d",&x,&y);
            to[x]=y;
        }
        for(int i=n-1;i>=0;i--)
        {
            if(to[i])
            {
                dp[i]=dp[to[i]];
                continue;
            }
            for(int j=i+1;j<=i+6;j++)
                dp[i]+=dp[j]/6;
            dp[i]+=1;
        }
        printf("%.4f\n",dp[0]);
    }
    return 0;
}