Time Limit: 1000MS | Memory Limit: 65536K | |
Total Submissions: 5153 | Accepted: 1404 |
Description
Input
Output
Sample Input
1 0.5 2 2 0.5 2 4
Sample Output
0.5000000 0.2500000
给n个有地雷的位置,给出走1步的概率和2步的概率,求能顺利通过这条路的概率。
首先对这n个点相邻两点排序分段[1,a[0]],[a[0]+1,a[1]] .......,假设k点有地雷,那么这个人肯定走k+1点,那么把n个点分成n段,每段起点的概率都相同,最后把每段不走地雷点的概率相乘就是结果。
由于区间长度特别大,不能O(n)递推,要用矩阵快速幂优化,很容易推出递推公式f(n)=f(n-1)*p+f(n-2)*(1-p),n点只能从n-1点和n-2点到。
代码:
#include <iostream> #include <cstdio> #include <cstring> #include <algorithm> using namespace std; struct matrix { double ma[4][4]; }; matrix multi(matrix x,matrix y) { matrix ans; memset(ans.ma,0,sizeof(ans.ma)); for(int i=1; i<=2; i++) { for(int j=1; j<=2; j++) { if(x.ma[i][j]) { for(int k=1; k<=2; k++) ans.ma[i][k]=ans.ma[i][k]+x.ma[i][j]*y.ma[j][k]; } } } return ans; } matrix pow(matrix a,int m) { matrix ans; for(int i=1; i<=2; i++) { for(int j=1; j<=2; j++) { if(i==j) ans.ma[i][j]=1; else ans.ma[i][j]=0; } } while(m) { if(m&1) ans=multi(ans,a); a=multi(a,a); m=m>>1; } return ans; } int main() { int a[15]; int n; double p; while(~scanf("%d%lf",&n,&p)) { double ans=1; matrix b,d; matrix c; for(int i=0; i<n; i++) scanf("%d",&a[i]); sort(a,a+n); b.ma[1][1]=p; b.ma[1][2]=1-p; b.ma[2][1]=1; b.ma[2][2]=0; memset(c.ma,0,sizeof(c.ma)); c.ma[1][1]=p; c.ma[2][1]=1; if(a[0]==1||a[0]==2) { if(a[0]==1) ans=0; else ans=ans*(1-p); } else { d=pow(b,a[0]-2); d=multi(d,c); ans=ans*(1-d.ma[1][1]); } for(int i=1; i<n; i++) { int temp=a[i]-a[i-1]; if(temp==1||temp==2) { if(temp==1) ans=0; else ans=ans*(1-p); } else { d=pow(b,temp-2); d=multi(d,c); ans=ans*(1-d.ma[1][1]); } } printf("%.7f\n",ans); } return 0; }
poj 3744 Scout YYF I(矩阵优化概率DP)
原文地址:http://blog.csdn.net/caduca/article/details/40742383