1. 程式人生 > >Discovering Gold LightOJ - 1030 || 概率與期望求法區別

Discovering Gold LightOJ - 1030 || 概率與期望求法區別

targe cas get amp %d 通過 sum -i lightoj

 1 #include<cstdio>//wrong_codes
 2 #include<algorithm>
 3 using namespace std;
 4 double ans[110],anss;
 5 int a[110],T,TT,n,endd;
 6 int main()
 7 {
 8     int i,j;
 9     scanf("%d",&T);
10     for(TT=1;TT<=T;TT++)
11     {
12         scanf("%d",&n);
13         for
(i=1;i<=n;i++) 14 scanf("%d",&a[i]); 15 for(i=1;i<=n;i++) 16 ans[i]=0; 17 anss=0; 18 ans[1]=1; 19 for(i=1;i<=n;i++) 20 { 21 endd=n-i<6?n-i:6; 22 for(j=1;j<=endd;j++) 23 ans[i+j]+=ans[i]/endd;
24 anss+=a[i]*ans[i]; 25 } 26 printf("Case %d: %.9lf\n",TT,anss); 27 } 28 return 0; 29 }

註意:雖然以上的代碼能通過,但是...下次還是不要用了。

代碼思路就是求出到達每一格的概率,然後每一格的金子乘上到達這一格的概率之和就是總期望。

但是,這樣做的時候會遇到很多難以理解的問題。比如以下一個看起來同樣有著合理的想法的方法:ans[i]表示到達i格拿到的金幣期望,再做一些很顯然的遞推。這個就是錯誤的。

順推的話,相比倒推,更容易出錯/遺漏/...。

 1 #include<cstdio>//wrong_codes
 2 #include<algorithm>
 3 using namespace std;
 4 double ans[110];
 5 int a[110],T,TT,n;
 6 int main()
 7 {
 8     int i,j;
 9     scanf("%d",&T);
10     for(TT=1;TT<=T;TT++)
11     {
12         scanf("%d",&n);
13         for(i=1;i<=n;i++)
14             scanf("%d",&a[i]);
15         for(i=1;i<=n;i++)
16             ans[i]=0;
17         ans[1]=a[1];
18         for(i=2;i<=min(n,6);i++)
19         {
20             for(j=1;j<i;j++)
21                 ans[i]+=ans[j];
22             ans[i]/=(i-1);
23             ans[i]+=(double)a[i];
24         }
25         for(i=min(n,6)+1;i<=n;i++)
26         {
27             for(j=1;j<=6;j++)
28                 ans[i]+=ans[i-j];
29             ans[i]/=6;
30             ans[i]+=(double)a[i];
31         }
32         printf("Case %d: %.9lf\n",TT,ans[n]);
33     }
34     return 0;
35 }

正確的做法就是:概率正推,期望倒推。http://blog.csdn.net/nameofcsdn/article/details/52082746

ans[i]表示從i格出發得到gold的期望。ans[i]=sum{ans[i+p]}(1<=p<=6)+a[i]

Discovering Gold LightOJ - 1030 || 概率與期望求法區別