POJ3744 Scout YYF I (概率DP + 矩陣優化)

bigbigship發表於2014-12-24

題目連結:

http://poj.org/problem?id=3744


題意:

有一段路,路上有n個陷阱,每一次只能向前走一步或者兩步,求安全走過這段路的改路


分析:

設dp[i]表示安全走過第i個陷阱的概率

那麼dp[i+1]=dp[i]*(1-p(走到第i+1個陷阱))

因為每次只能走一步或者兩步,所有安全走過第i個陷阱後的位置一定在a[i]+1;\

其中a[i]表示第i個陷阱的位置

求從a[i]+1,走到a[i+1]的概率的時候我們需要用到矩陣來經行優化

ans[i]表示走到位置i的概率

ans[i] = p*ans[i-1]+(1-p)*ans[i-2];

ans[0]=0,ans[1]=1;


程式碼如下:

#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
using namespace std;

const int maxn = 15;

double dp[maxn];
int a[maxn];
double p;
struct matrix{
    double a[2][2];
};

matrix I={
    1,0,
    0,1
};

matrix multi(matrix A,matrix B)
{
    matrix C;
    for(int i=0;i<2;i++){
        for(int j=0;j<2;j++){
            C.a[i][j]=0;
            for(int k=0;k<2;k++)
                C.a[i][j]+=A.a[i][k]*B.a[k][j];
        }
    }
    return C;
}

double pow(matrix A,int b)
{
    matrix ans = I;
    if(b<0) return 0;
    if(b==0) return 1;
    while(b){
        if(b&1) ans=multi(A,ans),b--;
        b>>=1;
        A=multi(A,A);
    }
    return ans.a[0][0];
}

int main()
{
    int n;
    while(~scanf("%d%lf",&n,&p)){
        memset(dp,0,sizeof(dp));
        dp[0]=1.0;
        for(int i=1;i<=n;i++)
            scanf("%d",a+i);
        a[0]=0;
        sort(a,a+n+1);
        matrix A={p,1-p,1,0};
        for(int i=1;i<=n;i++){
            dp[i]=dp[i-1]*(1-pow(A,a[i]-a[i-1]-1));
        }
        printf("%.7lf\n",dp[n]);
    }
    return 0;
}


相關文章