概率dp入门题,转移方程为dp[i]=dp[i-1]*p+dp[i-2]*(1-p)
因为n个数字上限很大,所以常规的概率dp基本不可能,要用矩阵优化。
把路程分成n+1段,分别计算通过每段的成功率,即刚好跨越地雷的概率(dp[地雷x+1])
算好每段之后把每段的成功率相乘。
(若有两颗地雷相邻那么成功率是0)
#include<iostream> #include<cstdio> #include<vector> #include<set> #include<map> #include<string.h> #include<cmath> #include<algorithm> #include<queue> #include<stack> #define LL long long #define mod 1000000007 #define inf 0x3f3f3f3f #define N 20 using namespace std; struct node { int n; double rect[N][N]; struct node operator* (const node b) { node tem; tem.n=n; for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) { tem.rect[i][j]=0; for(int k=1;k<=n;k++) tem.rect[i][j]+=rect[i][k]*b.rect[k][j]; } return tem; }; }; node pin(node a,LL b)//aµÄb´ÎÃÝ { node ans; ans.n=a.n; for(int i=1;i<=a.n;i++) for(int j=1;j<=a.n;j++) { if(i==j) ans.rect[i][j]=1; else ans.rect[i][j]=0; } while(b) { if(b&1) ans=a*ans; b>>=1; a=a*a; } return ans; } int main() { int n; while(~scanf("%d",&n)) { double p; scanf("%lf",&p); LL a[20]; double b[20]; double sum=1; for(int i=1;i<=n;i++) scanf("%lld",&a[i]); sort(a+1,a+1+n); a[0]=0; node tem; tem.n=2; tem.rect[1][1]=p; tem.rect[1][2]=1; tem.rect[2][1]=1-p; tem.rect[2][2]=0; //printf("%lf\n",pin(tem,4).rect[1][1]); for(int i=n;i>=1;i--) { a[i]-=(a[i-1]+2); if(a[i]<0) { b[i]=0; continue; } node ans=pin(tem,a[i]); b[i]=ans.rect[1][1]*(1-p); //cout << "b" << i << "= " << b[i] << endl; } for(int i=1;i<=n;i++) { sum*=b[i]; } printf("%.7f\n",sum); } return 0; }