poj 3774 Scout YYF I (矩阵优化的概率DP)
题意: n个雷,分别在a[1]...a[n] ,走一步概率为 p ,走两步概率为 1-p ,一开始在 1 号位置,问安全到达终点的概率。
思路:
将整个过程划分成阶段处理:
1 ~ a[1]
a[1]+1 ~ a[2]
…………
a[n-1]+1 ~ a[n]
那么只要求出每次踩到雷的概率,求反面,再把所有阶段结果连乘就可以了。
ans[i]表示踩中i的概率,那么可推倒出 ans[i]=p*ans[i-1]+(1-p)*ans[i-2]
因为直接暴力求解超时,构造矩阵
关于矩阵乘法 http://blog.csdn.net/lvshubao1314/article/details/26337911
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #include<cmath> using namespace std; int a[10]; int n; double p; struct Martix { double m[2][2]; }; //Martix A={p,1-p,1,0}; Martix I={1,0,0,1}; Martix multi(Martix x,Martix y) { Martix ans; for(int i=0;i<2;i++) for(int j=0;j<2;j++) { ans.m[i][j]=0; for(int k=0;k<2;k++) ans.m[i][j]+=x.m[i][k]*y.m[k][j]; } return ans; } Martix power(Martix x,int k) { Martix ans=I; while(k) { if(k&1) ans=multi(ans,x); x=multi(x,x); k>>=1; } return ans; } int main() { while(scanf("%d%lf",&n,&p)!=EOF) { for(int i=0;i<n;i++) { scanf("%d",&a[i]); } sort(a,a+n); int now=1; double ans=1; Martix A={p,1-p,1,0}; for(int i=0;i<n;i++) { Martix sum=power(A,a[i]-now); now=a[i]+1; ans*=(1-sum.m[0][0]); //printf("%.7f\n",A.m[0][0]); } printf("%.7f\n",ans); } return 0; }