Scout YYF I POJ - 3744(概率dp + 矩阵快速幂)
Posted wtsruvf
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Scout YYF I POJ - 3744(概率dp + 矩阵快速幂)相关的知识,希望对你有一定的参考价值。
题意:
一条路上有n个地雷,你从1开始走,单位时间内有p的概率走一步,1-p的概率走两步,问安全通过这条路的概率
解析:
很容易想到 dp[i] = p * dp[i-1] + (1 - p) * dp[i];
然而。。。t,但这个式子明显可以用矩阵快速幂加个氮气一下加速一下。。。
把所有的点输入之后 sort一下,那么就能把这条路分成很多段 每一段以地雷为分界线
1 - x[0] x[0]+1 - x[1] x[1]+1 - x[2] `````````
然后求出安全通过每一段的概率 乘一下就好了
呐 公式是这个 让 a = p b = (1 - p) 就好啦
代码是我改了一下bin神的 为什么要改。。。我没大懂大佬们写的多一次方啥意思。。。然后 就讨论了一下范围计算
#include<stdio.h> #include<string.h> #include<algorithm> #include<iostream> #include<math.h> using namespace std; struct Matrix { double mat[2][2]; }; Matrix mul(Matrix a,Matrix b) { Matrix ret; for(int i=0;i<2;i++) for(int j=0;j<2;j++) { ret.mat[i][j]=0; for(int k=0;k<2;k++) ret.mat[i][j]+=a.mat[i][k]*b.mat[k][j]; } return ret; } Matrix pow_M(Matrix a,int n) { Matrix ret; memset(ret.mat,0,sizeof(ret.mat)); for(int i=0;i<2;i++)ret.mat[i][i]=1; Matrix temp=a; while(n) { if(n&1)ret=mul(ret,temp); temp=mul(temp,temp); n>>=1; } return ret; } int x[30]; int main() { int n; double p; while(cin >> n >> p) { for(int i=0;i<n;i++) scanf("%d",&x[i]); sort(x,x+n); if(x[0] == 1) { puts("0.0000000"); continue; } double ans=1; Matrix tt; tt.mat[0][0]=p; tt.mat[0][1]=1-p; tt.mat[1][0]=1; tt.mat[1][1]=0; Matrix temp; if(x[0] > 2) { temp=pow_M(tt,x[0]-2); ans*=(1-(temp.mat[0][0] * p + temp.mat[0][1])); } else if(x[0] == 2) ans *= (1 - p); for(int i=1;i<n;i++) { if(x[i]==x[i-1])continue; if(x[i]-x[i-1] > 2) { temp=pow_M(tt,x[i]-x[i-1]-2); ans *= (1-(temp.mat[0][0] * p + temp.mat[0][1])); } else if(x[i]-x[i-1] == 2) ans *= (1 - p); else if(x[i] - x[i-1] == 1) ans = 0; } printf("%.7f ", ans); } return 0; }
以上是关于Scout YYF I POJ - 3744(概率dp + 矩阵快速幂)的主要内容,如果未能解决你的问题,请参考以下文章
POJ3744 Scout YYF I (矩阵优化的概率DP)
POJ 3744:Scout YYF I 概率DP+特征方程+快速幂