概率dp
此题的巧妙之处在于倒推,如果正推状态转移无法正确进行。令f[i]表示从i到游戏结束所需要的期望步数,则(1)f[i] = f[j],强制转移(2)f[i] = (f[j] + 1) / 6,共6种合法情况。则答案变成f[0]的值。代码如下:
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <cmath> 5 #include <algorithm> 6 #include <map> 7 #include <stack> 8 #include <string> 9 #include <ctime> 10 #include <queue> 11 #define mem0(a) memset(a, 0, sizeof(a)) 12 #define mem(a, b) memset(a, b, sizeof(a)) 13 #define lson l, m, rt << 1 14 #define rson m + 1, r, rt << 1 | 1 15 #define eps 0.0000001 16 #define lowbit(x) ((x) & -(x)) 17 #define memc(a, b) memcpy(a, b, sizeof(b)) 18 #define xx(a) ((a) * (a)) 19 using namespace std; 20 #define LL __int64 21 #define DB double 22 #define pi 3.14159265359 23 #define MD 10000007 24 #define INF (int)1e9 25 double f[110000]; 26 int last[110000]; 27 int main() 28 { 29 //freopen("input.txt", "r", stdin); 30 int n, m; 31 while(cin>> n>> m, n || m) { 32 mem0(last); 33 for(int i = 1; i <= m; i++) { 34 int u, v; 35 cin>> u>> v; 36 last[u] = v; 37 } 38 mem0(f); 39 for(int i = n - 1; i >= 0; i--) { 40 if(last[i]) { 41 f[i] = f[last[i]]; 42 continue; 43 } 44 for(int j = 1; j <= 6; j++) f[i] += (f[i + j] + 1) / 6; 45 } 46 printf("%.4f\n", f[0]); 47 } 48 return 0; 49 }