Discovering Gold(概率dp 期望入門)
阿新 • • 發佈:2018-12-11
題意
有一排洞穴,你在第一個洞穴,可以獲得該洞穴的黃金,然後擲標有1-6的骰子,
是幾就往下走幾步,並得到該洞穴的黃金。
當離終點小於6步且不合法時就重擲直到合法為止。
求起點出發的黃金的期望。
題解
概率dp入門題。
考慮到自己dp比較菜,概率dp更菜,就做一個總結一個吧。
就是你在這點的期望,等於這個點的黃金數,加上你能走到所有的所有合法點的期望的平均。
那我能走到的所有合法點期望怎麼求?
顯然是從後往前dp,或者遞迴搜尋。
程式碼
#include <iostream> #include <algorithm> #include <string> #include <cstring> #include <cstdio> #include <cmath> #include <set> #include <map> #include <vector> #include <stack> #include <queue> #include <bitset> const int INF=0x3f3f3f3f; const int mod=1e9+7; const double eps=1e-7; typedef long long ll; #define vi vector<int> #define si set<int> #define pii pair<int,int> #define pi acos(-1.0) #define pb push_back #define mp make_pair #define lowbit(x) (x&(-x)) #define sci(x) scanf("%d",&(x)) #define scll(x) scanf("%lld",&(x)) #define sclf(x) scanf("%lf",&(x)) #define pri(x) printf("%d",(x)) #define rep(i,j,k) for(int i=j;i<=k;++i) #define per(i,j,k) for(int i=j;i>=k;--i) #define mem(a,b) memset(a,b,sizeof(a)) using namespace std; double dp[105];//dp[i]表示從i點出發到n點的期望 int main() { int t; sci(t); rep(k,1,t) { mem(dp,0); int n; sci(n); rep(i,0,n-1)scanf("%lf",&dp[i]); per(i,n-2,0) { int step=min(6,(n-1-i));//step為可以向前走的步數的最大值 rep(j,1,step)//j為實際往前走的步數 { dp[i]+=dp[i+j]/step;//有1/6的概率走到i+step獲得i+step的期望 //注意如果step<6比如說step=4,這裡會重複投骰子直至合法,故走到以後四個點的概率均為1/4 //用回溯的方法 將未來沒有走到的點的期望都累加到前面的點上 } } printf("Case %d: %.7lf\n",k,dp[0]); } return 0; }