HDU 4405 Aeroplane chess:期望dp

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4405

题意:

  你在下简化版飞行棋。。。

  棋盘为一个线段,长度为n。

  上面有m对传送门,可以直接将你从a[i]传送到b[i]处。

  每扔一次骰子,可以向前移动的步数为骰子的点数。

  你的初始位置为0。当位置>=n时,游戏结束。

  问你扔骰子次数的期望。

题解:

  表示状态:

    dp[i] = rest steps

    位置为i时,剩余需要掷骰子次数的期望。

  找出答案:

    ans = dp[0](初始位置)

  如何转移:

    每次掷骰子点数分别为1至6的概率均为1/6。

    dp[i] = sigma (dp[i+j] * 1/6) + 1

    特别地,当i为某个传送门的入口时,只能转移到出口处。所以此时dp[i] = dp[trans[i]].

  边界条件:

    set dp = 0

    i >= n表明游戏已经结束,dp[i]为0.

    i < n的dp[i]会在for循环中更新,所以不用管。

AC Code:

 1 // state expression:
 2 // dp[i] = rest steps
 3 // i: present pos
 4 //
 5 // find the answer:
 6 // ans = dp[0]
 7 //
 8 // transferring:
 9 // now: dp[i]
10 // dp[i] = sigma (dp[i+j] * 1/6) + 1
11 //
12 // boundary:
13 // set dp = 0
14 #include <iostream>
15 #include <stdio.h>
16 #include <string.h>
17 #define MAX_N 100010
18 
19 using namespace std;
20 
21 int n,m;
22 int trans[MAX_N];
23 double dp[MAX_N];
24 
25 void read()
26 {
27     memset(trans,-1,sizeof(trans));
28     int a,b;
29     for(int i=0;i<m;i++)
30     {
31         cin>>a>>b;
32         trans[a]=b;
33     }
34 }
35 
36 void solve()
37 {
38     memset(dp,0,sizeof(dp));
39     for(int i=n-1;i>=0;i--)
40     {
41         if(trans[i]!=-1)
42         {
43             dp[i]=dp[trans[i]];
44             continue;
45         }
46         for(int j=1;j<=6;j++)
47         {
48             dp[i]+=dp[i+j]/6.0;
49         }
50         dp[i]+=1.0;
51     }
52 }
53 
54 void print()
55 {
56     printf("%.4f
",dp[0]);
57 }
58 
59 int main()
60 {
61     while(cin>>n>>m)
62     {
63         if(n==0 && m==0) break;
64         read();
65         solve();
66         print();
67     }
68 }
原文地址:https://www.cnblogs.com/Leohh/p/7572236.html