题意:YYF从坐标1出发,每次走一步的概率是p,走两步的概率是1-p,然后有n个点上有地雷。问YYF走过雷区的概率是多少。
解法:ans[i]表示走到i的概率。概率公式ans[i]=p*ans[i-1]+(1-p)ans[i-2]
转移矩阵:
ans[i] | p ,1-p | ans[i-1]
=| |*
ans[i-1] | 1 , 0 | ans[i-2]
根据每个地雷的位置分段计算概率;
代码:
/****************************************************** * author:xiefubao *******************************************************/ #pragma comment(linker, "/STACK:102400000,102400000") #include <iostream> #include <cstring> #include <cstdlib> #include <cstdio> #include <queue> #include <vector> #include <algorithm> #include <cmath> #include <map> #include <set> #include <stack> #include <string.h> //freopen ("in.txt" , "r" , stdin); using namespace std; #define eps 1e-8 const double pi=acos(-1.0); typedef long long LL; const int Max=15; int m=2; int n; double p; int mine[Max]; struct matrix { double num[3][3]; matrix(){ memset(num,0,sizeof num); } }; matrix operator*(const matrix& a,const matrix& b) { matrix ans; for(int i=0;i<m;i++) for(int j=0;j<m;j++) for(int k=0;k<m;k++) ans.num[j][k]+=a.num[j][i]*b.num[i][k]; return ans; } matrix pow(matrix mat,int t) { matrix ans; ans.num[0][0]=1; ans.num[1][1]=1; while(t) { if(t&1) ans=ans*mat; mat=mat*mat; t>>=1; } return ans; } double getans(int t) { if(t<=1) return 0; if(t==2) return 1; if(t==3) return p; t-=3; matrix tool; tool.num[0][0]=p; tool.num[0][1]=1-p; tool.num[1][0]=1; tool.num[1][1]=0; tool=pow(tool,t); //cout<<tool.num[0][0]<<" "<<tool.num[0][1]<<" "<<p<<endl; return tool.num[0][0]*p+tool.num[0][1]; } int main() { while(scanf("%d%lf",&n,&p)==2) { mine[0]=0; for(int i=1;i<=n;i++) scanf("%d",mine+i); sort(mine+1,mine+n+1); double out=1; for(int i=1;i<=n;i++) { out*=getans(mine[i]-mine[i-1]); out*=(1.0-p); } printf("%.7lf\n",out); } return 0; }
poj3744(概率dp+快速幂),布布扣,bubuko.com
原文地址:http://blog.csdn.net/xiefubao/article/details/29200525