您的位置:首页 > 其它

poj 3744(概率dp、矩阵快速幂)

2018-01-24 12:04 337 查看
/*

    poj 3744

    题目大概是

    小明要走一段路

    有p的概率走一步

    (1-p)的概率走两步

    然后上面有雷

    问安全通过的概率

    题目通过雷把路程分为多段

    把每段安全通过的概率相乘

    就是整段安全通过的概率

    设dp[i]是小明安全到i的概率

    到i的方式有两种

    一种是从(i-1)走一步

    第二种是从(i-2)走两步

    所以安全到dp[i]的概率就是

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

    因为数据问题

    用矩阵来优化代码

    最后把所求的每一段相乘即可

*/

#include <iostream>

#include <algorithm>

#include <stdio.h>

#include <math.h>

#include <string.h>

#define mod 1000000007

#define MAX 100005

#define ll long long

#define PI acos(-1)

using namespace std;

struct matrix

{

    double m[2][2];

}mat;

int res[15];

matrix matrixmul(matrix a,matrix b)

{

    matrix c;

    for(int i=0; i<2; i++)

        for(int j=0; j<2; j++)

        {

            c.m[i][j]=0;

            for(int k=0; k<2; k++)

                c.m[i][j]+=(a.m[i][k]*b.m[k][j]);

        }

    return c;

}

matrix quickpow(matrix m,ll n)

{

    matrix b;

    memset(b.m,0,sizeof(b.m));

    b.m[0][0]=b.m[1][1]=1;

    while(n>=1)

    {

        if(n&1)

            b=matrixmul(b,m);

        n=n>>1;

        m=matrixmul(m,m);

    }

    return b;

}

int main()

{

    double ans[15];

    int n;

    double p;

    while(cin>>n>>p)

    {

        mat.m[0][0]=p;

        mat.m[0][1]=1-p;

        mat.m[1][0]=1;

        mat.m[1][1]=0;

        memset(res,0,sizeof(res));

        for(int i=1;i<=n;i++)

            cin>>res[i];

        sort(res+1,res+1+n);

        matrix tmp=quickpow(mat,res[1]-1);

        ans[1]=1-tmp.m[0][0];//求安全通过第一段的概率

        for(int i=2;i<=n;i++)//求从第(i-1)个雷安全到第i个雷的概率

        {

            tmp=quickpow(mat,res[i]-res[i-1]-1);

            ans[i]=1-tmp.m[0][0];

        }

        double rel=1;

        for(int i=1;i<=n;i++)//全部相乘得结果

        {

            rel*=ans[i];

        }

        printf("%.7lf\n",rel);

    }

    return 0;

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: