HDU 4405(概率dp入門)
說是概率DP,其實主要是求概率和期望的問題
說到DP總要有狀態,每種狀態可能有多種子狀態
一般的DP是這樣:在DP過程中,當前狀態必然是由多個子狀態中的最優的轉移而來
所以一般的DP求的是最優的結果
而概率不需要最優,而是實際概率
所以概率DP最大的區別在於:在DP過程中,當前狀態是由所有子狀態的概率共同轉移而來
所以概率DP只是利用了DP的動態而沒有規劃 (只有狀態轉移,而不需要進行決策)
Aeroplane chessTime Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 5665 Accepted Submission(s): 3541 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 |
設dp[i] 為從第i個點到終點需要投擲的次數,
那麼 dp[i] = ∑(j = 1, 6)dp[i+j]*p(j) + 1 , 其中p(j) 為投擲結果為 j 的概率, + 1 是因為從此一步到下一步 一定會 投擲一次
AC程式碼:
#include<cstdio>
#include<cstring>
using namespace std;
const int maxn = 100050;
double dp[maxn];
int h[maxn];
int main()
{
int n,m;
while(~scanf("%d%d",&n,&m)){
if(!n && !m) break;
memset(dp,0,sizeof(dp));
memset(h,0,sizeof(h));
int x,y;
for(int i = 0;i < m;i ++){
scanf("%d%d",&x,&y);
h[x] = y;
}
for(int i = n - 1;i >= 0;i --){
if(h[i]) dp[i] = dp[h[i]];
else {
for(int j = 1;j <= 6;j ++)
dp[i] += 1.0/6 * dp[i+j];
dp[i] += 1;
}
}
printf("%.4lf\n",dp[0]);
}
return 0;
}