现在的位置: 首页 > 综合 > 正文

POJ 3744 Scout YYF I 矩阵快速幂加速dp

2018年04月25日 ⁄ 综合 ⁄ 共 1430字 ⁄ 字号 评论关闭

题意:在坐标范围在[1,100000000]内有10个mine,有一个人从1出发,有p的概率向前走一步,1-p的概率向前走两步,问该人能顺利通过不踩到一个mine的概率是多少。
题解:因为人只能向前走一步或者两步,所以最后人到达pos[n]+1位置的概率即为答案(如果可以到达,否则为0),想到dp[i]表示该人到达坐标为 i 的位置的概率,
         即dp[i] = dp[i-1] * p + dp[i-2] * (1 - p);但是坐标范围很大,考虑矩阵快速幂加速,因为如果该地方有mine则概率为0,所以需要在每两个mine之间进行一次矩阵快速
         幂即可。每次都是[ans , 0] * [p , 1.0 , 1-p , 0]矩阵相乘。

Sure原创,转载请注明出处。

#include <iostream>
#include <cstdio>
#include <memory.h>
#include <algorithm>
using namespace std;
const double eps = 1e-8;
const int maxn = 12;
struct matrix
{
    double mat[2][2];
    void clear()
    {
        mat[0][1] = mat[1][0] = 0.0;
        mat[0][0] = mat[1][1] = 1.0;
        return;
    }
}tran,res;
int pos[maxn];
int n;
double p;

void read()
{
    for(int i=0;i<n;i++)
    {
        scanf("%d",&pos[i]);
    }
    sort(pos,pos+n);
    return;
}

void init()
{
    tran.mat[0][0] = p;
    tran.mat[0][1] = 1.0;
    tran.mat[1][0] = 1.0 - p;
    tran.mat[1][1] = 0;
    return;
}

inline matrix mul(matrix a , matrix b)
{
    matrix c;
    c.mat[0][0] = c.mat[0][1] = c.mat[1][0] = c.mat[1][1] = 0.0;
    for(int k=0;k<2;k++)
    {
        for(int i=0;i<2;i++)
        {
            for(int j=0;j<2;j++)
            {
                c.mat[i][j] += a.mat[i][k] * b.mat[k][j];
            }
        }
    }
    return c;
}

void powmi(int x)
{
    matrix tmp = tran;
    res.clear();
    while(x)
    {
        if(x & 1)
        {
            res = mul(res , tmp);
        }
        tmp = mul(tmp , tmp);
        x >>= 1;
    }
    return;
}

bool check()
{
    for(int i=0;i<n-1;i++)
    {
        if(pos[i+1] - pos[i] < 2) return false;
    }
    return true;
}

void solve()
{
    if(pos[0] == 1 || check() == false)
    {
        puts("0.0000000");
        return;
    }
    double ans = 1.0;
    int step = pos[0] - 2;
    for(int i=0;i<n;i++)
    {
        powmi(step);
        ans *= res.mat[0][0];
        ans *= 1.0 - p;
        if(i < n-1) step = pos[i+1] - pos[i] - 2;
    }
    printf("%.7f\n",ans);
    return;
}

int main()
{
    while(~scanf("%d %lf",&n,&p))
    {
        read();
        init();
        solve();
    }
    return 0;
}

抱歉!评论已关闭.