hdu4405:Aeroplane chess

题目大意:有编号为0-n的格子,从0开始,扔骰子扔到几就走几格。有m个瞬移点,每个点可以从格x直接飞到格y,若瞬移到另一个瞬移点可以继续瞬移。求到达格n的期望扔骰子次数。

题解:期望DP入门好题。网上神犇们都说,“经验表明,一般情况下,求期望的题从后往前推。”本蒟蒻一开始不明白,谁给你的权利一定要从后往前啊!于是我就写了这样一个式子:

E(i)——到格i期望,E(i)=i是某个瞬移目标点?(E(x),x指瞬移出发点),否则E(i-1)*1/6+E(i-2)*1/6+...+E(i-6)*1/6+1,注意最后把“又走了一步”加上。标准全期望公式。于是高高兴兴地通过了第一组数据。然后测试第二组。。。。。。那么问题究竟出在哪里呢?

问题一:若i是瞬移目标点,在平均的情况下,凭什么一定认为到达i的情况和到达i对应的出发点的情况完全一样?显然

 在上图情况中,0到2的所有方法并不对应到5的所有方法。如果按原先的思路,那么0->3->5等的情况将被无情地忽略。

问题二:i格走到后面1-6格的概率为1/6,不!能!认!为!i格前1-6格走到i的概率为1/6。虽然在m=0的时候这两者碰巧等价了,但加入瞬移点后,到达一个格的方法多种多样,概率当然不尽相同,而一个格向前运行的概率是永恒的。

通往目标的路变幻莫测,而我们向前发展的步伐是永恒的。

言归正传,我们只能从目标退回来。E(i)——i格到n的期望,E(i)=E(i+1)*1/6+...+E(i+6)*1/6+1,边界是E(n),严格的,E(n),E(n+1),...,E(n+5)=0。E(0)即为所求。至于瞬移出发点,E(i)=E(go(i)),go(i)指瞬移到达点。虽然看起来跟之前差不多,但这样做无可厚非。

代码:

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<algorithm>
 4 #include<cmath>
 5 #include<iostream>
 6 using namespace std;
 7 
 8 int n,m;
 9 #define maxn 100011
10 int go[maxn];double E[maxn];
11 #define eof 1e-9
12 int main()
13 {
14     while (scanf("%d%d",&n,&m) && (n || m))
15     {
16         memset(go,0,sizeof(go));
17         for (int i=1;i<=m;i++)
18         {
19             int x,y;scanf("%d%d",&x,&y);
20             go[x]=y;
21         }
22         memset(E,0,sizeof(E));
23         for (int i=n-1;i>=0;i--)
24         {
25             if (!go[i]) {for (int j=1;j<=6;j++) E[i]+=E[j+i]/6.0;E[i]+=1;}
26             else E[i]=E[go[i]];
27         }
28         printf("%.4lf
",E[0]);
29     }
30     return 0;
31 }
View Code
原文地址:https://www.cnblogs.com/Blue233333/p/6241831.html