题目链接:http://lightoj.com/volume_showproblem.php?problem=1030
题意:在一个1*n 的格子里,每个格子都有相应的金币数,走到相应格子的话,就会得到该格子的金币。
现在有一个人在1这个位置,手里有一颗骰子,骰子摇到几,他就前进几步,但如果当前位置+骰子数 > n,那么他就会重新摇色子一直到<=n为止。
走到n这个位置的话,意味着游戏结束了。 问游戏结束时,这个人得到金币的期望。
设dp[i]表示从i号格子出去的期望,所以dp[i]是和i后面的紧接着6个数有关, 那么 则有dp[i] = (dp[i+1]/6 + ... + dp[i+6]/6) + dp[i]。
初始化dp[i] = 第i个格子的gold值。
#include <cstring> #include <cstdio> #include <iostream> #include <algorithm> #include <cmath> #include <stack> #include <vector> #include <queue> using namespace std; #define N 105 #define met(a, b) memset(a, b, sizeof(a)) typedef long long LL; int main() { int T, t = 1, n; scanf("%d", &T); while(T--) { double dp[N]; int a[N]; met(dp, 0); scanf("%d", &n); for(int i=1; i<=n; i++) scanf("%d", &a[i]); dp[n] = a[n]; for(int i=n-1; i>=1; i--) { dp[i] = a[i]; int k = min(6, n-i); for(int j=1; j<=k; j++) dp[i] += dp[i+j]/k; } printf("Case %d: %.6f ", t++, dp[1]); } return 0; }
还有就是可以先求出到达每个格子的概率dp[i],然后再乘上格子的金币数就是所求期望了;
#include <cstring> #include <cstdio> #include <iostream> #include <algorithm> #include <cmath> #include <stack> #include <vector> #include <queue> using namespace std; #define N 105 #define met(a, b) memset(a, b, sizeof(a)) typedef long long LL; int main() { int T, t = 1, n; scanf("%d", &T); while(T--) { double dp[N]; int a[N]; met(dp, 0); scanf("%d", &n); for(int i=1; i<=n; i++) scanf("%d", &a[i]); dp[1] = 1.0; for(int i=1; i<=n; i++) { int k = min(6, n-i); for(int j=1; j<=k; j++) dp[i+j] += dp[i]/k; } double ans = 0; for(int i=1; i<=n; i++) ans += a[i]*dp[i]; printf("Case %d: %.6f ", t++, ans); } return 0; }