【HDU4405】Aeroplane chess(概率dp)
Aeroplane chessTime 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.
Input There are multiple test cases.
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;
}