poj-3744 Scout YYF I [用矩陣優化概率遞推式]
阿新 • • 發佈:2019-01-30
/* 題意:在一條不滿地雷的路上,你現在的起點在1處。 在N個點處布有地雷,1<=N<=10。地雷點的座標範圍:[1,100000000]. 每次前進p的概率前進一步,1-p的概率前進兩步。 問順利通過這條路的概率。就是不要走到有地雷的地方。 dp[i] 表示走到i的概率 dp[i+1]=dp[i]*p+dp[i-1]*(1-p); 用矩陣快速冪優化 遞推式轉矩陣 | 0 1| |dp(k-1)| = | dp(k) | | 1-p p| | dp(k) | | dp(k+1)| dp[0]=0,dp[1]=1; 設x[i] 表示第i個地雷的位置 把道路分成開 1~x[1] x[1]+1~x[2]...... x[n-1]+1~x[n] 對於每一段 sus[i] 表示 x[i-1]+1~x[i]-1這一段沒有掛掉 那麼sus[i]= 1-從x[i-1]+1剛好走到x[i]的概率; 那麼 ans為sus[i]的總乘積(即每一段都沒屎) */ #include <stdio.h> #include <algorithm> #include <vector> using namespace std; typedef vector<double> vec; typedef vector<vec> mat; const int maxn=30; const double eps=1E-8; int x[maxn]; int n; double p; mat mul(const mat &a,const mat &b) { mat c(2,vec(2,0)); for(int i=0;i<2;++i) for(int j=0;j<2;++j) for(int k=0;k<2;++k) c[i][j]+=a[i][k]*b[k][j]; return c; } double T(int k) { double s[2][2]={{0,1},{1-p,p}}; mat A(2,vec(2)); mat p(2,vec(2,0)); p[0][0]=p[1][1]=1; for(int i=0;i<2;++i) for(int j=0;j<2;++j) A[i][j]=s[i][j]; while(k>0) { if(k&1) p=mul(A,p); k=k>>1; A=mul(A,A); } return p[1][1]; } void DP() { double ans=1; double tmp=T(x[1]-1); ans*=(1-tmp); for(int i=2;i<=n;++i) { if(x[i]==x[i-1]) continue; tmp=1-T(x[i]-x[i-1]-1); ans*=tmp; } printf("%.7f\n",ans<eps?0:ans); } int main() { while(~scanf("%d %lf",&n,&p)) { for(int i=1;i<=n;++i) scanf("%d",x+i); sort(x+1,x+1+n); DP(); } return 0; }