poj3744 Scout YYF I(概率dp+矩阵加速)

本文介绍了一种解决特定雷区概率问题的方法,利用矩阵乘法加速递归过程,并结合斐波那契数列特性简化计算。文章提供了一个完整的C++实现案例,通过矩阵快速幂来高效求解安全路径的概率。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目链接

分析:
可以看出一个很naive的转移方程:
f[i]=pf[i1]+(1p)f[i2] f [ i ] = p ∗ f [ i − 1 ] + ( 1 − p ) ∗ f [ i − 2 ] i1,i2 i − 1 , i − 2 都不是地雷)

在两个相邻的地雷之中,有一段安全区域
我突然发现,通过这个安全区域的方案数恰好是斐波那契数列 f[i]=f[i1]+f[i2] f [ i ] = f [ i − 1 ] + f [ i − 2 ]

(方案数,立刻想到了这道题的处理方式,然而并没什么用)

计算斐波那契数列,一般都是使用矩阵乘法
那么这个转移方程我们也可以用矩阵加速
只要把安全区域和地雷分开考虑就好了

安全区域用矩阵,地雷直接乘上 (1p) ( 1 − p )

tip

注意特殊情况

想好矩阵每个位置代表的意义

献上一种很神的数学做法

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>

using namespace std;

struct node{
    double H[2][2];
    node operator *(const node &a) const {
        node ans;
        for (int i=0;i<=1;i++)
            for (int j=0;j<=1;j++) {
                ans.H[i][j]=0.0;
                for (int k=0;k<=1;k++)
                    ans.H[i][j]=ans.H[i][j]+H[i][k]*a.H[k][j];
            }
        return ans;
    }
    void clear() {
        for (int i=0;i<=1;i++) for (int j=0;j<=1;j++) H[i][j]=0.0;
    }
    node KSM(int k) {
        if (k==0) {
            node ans;
            ans.clear();
            ans.H[0][0]=ans.H[1][1]=1.0;
            return ans;
        }

        k--;
        node ans=(*this),a=(*this);
        while (k) {
            if (k&1) ans=ans*a;
            a=a*a;
            k>>=1;
        }
        return ans;
    } 
};
node H;

int n,a[12];
double p;

int main()
{
    while (scanf("%d%lf",&n,&p)!=EOF) {
        for (int i=1;i<=n;i++) scanf("%d",&a[i]);
        H.clear();
        H.H[0][0]=p; H.H[1][0]=1.0-p; H.H[0][1]=1.0;

        sort(a+1,a+1+n); a[0]=0;

        if (a[1]==1) {
            printf("%0.7lf\n",0);
            continue;
        }

        bool f=0;
        double ans=1;
        for (int i=1;i<=n;i++) {
            if (a[i]==a[i-1]+1) {f=1;break;}   //连续两个地雷 

            node A=H.KSM(a[i]-a[i-1]-2);
            ans=ans*A.H[0][0]*(1.0-p);
        }

        if (!f) printf("%.7lf\n",ans);
        else printf("%.7lf\n",0);
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值