Discovering Gold LightOJ - 1030 (概率dp)

 

You are in a cave, a long cave! The cave can be represented by a 1 x N grid. Each cell of the cave can contain any amount of gold.

Initially you are in position 1. Now each turn you throw a perfect 6 sided dice. If you get X in the dice after throwing, you add X to your position and collect all the gold from the new position. If your new position is outside the cave, then you keep throwing again until you get a suitable result. When you reach the Nth position you stop your journey. Now you are given the information about the cave, you have to find out the expected number of gold you can collect using the given procedure.

 

Input

Input starts with an integer T (≤ 100), denoting the number of test cases.

Each case contains a blank line and an integer N (1 ≤ N ≤ 100) denoting the dimension of the cave. The next line contains N space separated integers. The ith integer of this line denotes the amount of gold you will get if you come to the ith cell. You may safely assume that all the given integers will be non-negative and no integer will be greater than 1000.

 

Output

For each case, print the case number and the expected number of gold you will collect. Errors less than 10-6 will be ignored.

Sample Input

3

 

1

101

 

2

10 3

 

3

3 6 9

 

Sample Output

Case 1: 101.0000000000

Case 2: 13.000

Case 3: 15

 

题意:有一个1*n的洞穴,开始的时候你在第一个格子,你扔一个六面的筛子,扔到n你就走到你当前位置前面的第n个格子,然后你能得到这个格子里面存的黄金数(每到一个新格子就扔一次筛子)。

每个格子的黄金数已经给出,问你走到最后一个格子所能获得的总黄金数的期望。

 

思路:筛子只有1-6这6个数字,所以你每一步只能走到当前格子的前面6个格子中的一个,假设走到当前格子所能获得的期望值为dp[i],则dp[i] = ( dp[i+1]/6 +  ...  + dp[i+6]/6 ) + a[i]。(a[i]为当前格子含有的金子数)

想一想,你离终点越远,理论上你能获得的金子也就越多,因为可以走更多步,所以越接近起点,dp值越大。初始的dp【i】的值为第i个格子的金子数,然后要加上你走到的下一个位置所能

获得的金子的期望,下一个位置有六种可能,每种都是1/6;当然,还有特殊情况,那就是你当前位置与终点之间的距离小于6,那就特殊考虑,有几个格子上面的递推公式的分母就为几。

从终点往前递推,最后dp【1】的值就是答案。

看下面的代码理解一下吧(虽然我也是似懂非懂YwY)。

 

 1 #include<iostream>
 2 #include<algorithm>
 3 #include<cstring>
 4 #include<cstdio>
 5 using namespace std;
 6 int main()
 7 {
 8     int t,n,cnt=0;
 9     double a[1007],dp[1007];
10     cin>>t;
11     while(t--)
12     {
13         cin>>n;
14         memset(dp,0,sizeof(dp));
15         for(int i=1; i<=n; i++)
16             cin>>a[i];
17         dp[n] += a[n];
18         for(int i=n-1;i>=1;i--)
19         {
20             dp[i] += a[i];//当前点的期望等于后6个点的期望的 1/6 的和; 
21             int len = min(n-i,6);//判断当前点之后是否还有6个点 ,不够六个点则有几个算几个。
22             for(int j=i+1; j<=i+6 && j<=n; j++)
23             {
24                 dp[i] += dp[j]/len;
25             }
26         }
27         cout<<"Case "<<++cnt<<": ";
28         printf("%.7lf\n",dp[1]);
29     }
30     return 0;
31  }

 

posted @ 2018-05-03 18:20  特务依昂  阅读(207)  评论(0编辑  收藏  举报