poj3744 Scout YYF I 【概率dp+矩陣優化】
阿新 • • 發佈:2019-02-12
解題思路:
很容易想到設dp[i]表示安全走到i的概率,則dp[i]=p
但資料範圍是[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;
}