Scout YYF I POJ - 3744【矩阵乘法优化求概率】

题意:

  一条路上有 \(n\) 个地雷,YYF 从位置 \(1\) 出发,走一步的概率为 \(p\),走两步的概率是 \((1-p)\)。求 YYF 能顺利通过这条路的概率。
数据范围: \(1\leq n \leq 10\),\(0.25\leq p\leq 0.75\),输入的 \(n\) 个位置的范围:\([1,1e8]\)

分析:

  从前往后推,状态转移方程:\(dp[i]=dp[i-1]*p+dp[i-2]*(1-p)\),其中 \(dp[1]=1\),有地雷的位置 \(dp[i]=0\)。如果直接算,必然超时,可以用矩阵快速幂分段优化。

坑点:输入的 \(n\) 个位置不一定有序。

代码:

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
int a[15];
double p;
struct matrix
{
    double mat[3][3];
    void clc()
    {
        for(int i=0;i<3;i++)
            for(int j=0;j<3;j++)
                mat[i][j]=0;
    }
    void eye()
    {
        for(int i=1;i<=2;i++)
            mat[i][i]=1;
    }
    matrix operator *(const matrix b)const
    {
        matrix res;
        res.clc();
        for(int i=1;i<=2;i++)
        {
            for(int k=1;k<=2;k++)
            {
                for(int j=1;j<=2;j++)
                    res.mat[i][j]=(res.mat[i][j]+mat[i][k]*b.mat[k][j]);
            }
        }
        return res;
    }
};
matrix mpow(matrix a,int b)
{
    matrix res;
    res.clc();
    res.eye();
    while(b)
    {
        if(b&1)
            res=res*a;
        a=a*a;
        b>>=1;
    }
    return res;
}
void init(matrix &a)
{
    a.clc();
    a.mat[1][1]=1;
}
void init2(matrix &b)
{
    b.clc();
    b.mat[1][1]=p;
    b.mat[1][2]=1;
    b.mat[2][1]=1-p;
}
int main()
{
    int n,x,last;
    while(scanf("%d%lf",&n,&p)!=EOF)
    {
        for(int i=1;i<=n;i++)
            scanf("%d",&a[i]);
        sort(a+1,a+1+n);
        matrix A,B;
        init(A);
        init2(B);
        bool f=1;
        last=1;
        for(int i=1;i<=n;i++)
        {
            A=A*mpow(B,a[i]-last);//cout<<"A="<<A.mat[1][2]<<endl;
            A.mat[1][1]=0;
            last=a[1];
        }
        A=A*B;
        printf("%.7f\n",A.mat[1][1]);
    }
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/1024-xzx/p/12403065.html