1. 程式人生 > >poj3744 Scout YYF I 【概率dp+矩陣優化】

poj3744 Scout YYF I 【概率dp+矩陣優化】

解題思路:

很容易想到設dp[i]表示安全走到i的概率,則dp[i]=pdp[i-1]+(1-p)dp[i-2],然後有地雷的地方概率為0,最後dp[maxpos+1]就是答案;
但資料範圍是[1, 100000000],顯然過不了。

注意到地雷只有10個,所以可以把地圖分為10段,每兩個地雷之間的dp用矩陣優化就可以過了。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<algorithm>
#include<cmath>
#include<vector> #include<queue> #define ll long long using namespace std; int getint() { int i=0,f=1;char c; for(c=getchar();(c<'0'||c>'9')&&c!='-';c=getchar()); if(c=='-')f=-1,c=getchar(); for(;c>='0'&&c<='9';c=getchar())i=(i<<3)+(i<<1
)+c-'0'; return i*f; } struct Matrix { double a[3][3]; friend inline Matrix operator * (const Matrix &A,const Matrix &B) { Matrix res; memset(res.a,0,sizeof(res.a)); for(int i=1;i<=2;i++) for(int j=1;j<=2;j++) for(int k=1
;k<=2;k++) res.a[i][j]+=A.a[i][k]*B.a[k][j]; return res; } void I() { memset(a,0,sizeof(a)); a[1][1]=a[2][2]=1; } Matrix Pow(int y) { Matrix res,B=*this; res.I(); for(;y;y>>=1,B=B*B) if(y&1)res=res*B; return res; } }A,P; int n,pos[105]; double p; int main() { //freopen("lx.in","r",stdin); while(scanf("%d%lf",&n,&p)!=EOF) { for(int i=1;i<=n;i++) pos[i]=getint(); sort(pos+1,pos+n+1); if(pos[1]==1) { puts("0.0000000"); continue; } P.a[1][1]=0,P.a[2][1]=1,P.a[1][2]=1-p,P.a[2][2]=p; A.a[1][1]=0,A.a[1][2]=1; pos[0]=1; for(int i=1;i<=n;i++) { int dis=pos[i]-pos[i-1]-1; A=A*P.Pow(dis); A.a[1][1]=A.a[1][2]; A.a[1][2]=0; } A=A*P; printf("%0.7lf\n",A.a[1][2]); } return 0; }