Scout YYF I POJ - 3744 概率dp

Scout YYF I POJ - 3744

题意:这个题意很好懂~就是讲一个人要走一条路(一维),从坐标1开始走,在当前位置他往前走一步的概率是P,走两步的概率是1-p。然后路上有n个炸弹,问能安全走完这段路的概率是多少。

分析:
状态转移: dp[i]=dp[i-1]p+dp[i-2](1-p);
然后如果i位置有炸弹的话dp[i]=0;
但是炸弹的位置可以到1e8,这个都存不下,如果存的下也会超时…
再看一下状态转移,这个递推式可以用矩阵快速幂呀。
因为炸弹的数量最多到10,就可以分成10段来看。
比如x处有炸弹,那么一定会走到x-1处,我们只用把x-1处的概率求出来就行了

using namespace std;
#define ll long long
#define mem(a,b) memset(a,b,sizeof(a))
const int maxn = 1e6;
struct matrix
{
    double mat[5][5];
    matrix()
    {
        memset(mat,0,sizeof(mat));
    }
};
matrix mul(matrix A,matrix B)
{
    matrix C;
    for(int i=0;i<2;i++)
    {
        for(int j=0;j<2;j++)
        {
            for(int k=0;k<2;k++)
            {
                C.mat[i][j]=C.mat[i][j]+A.mat[i][k]*B.mat[k][j];
            }
        }
    }
    return C;
}
matrix quickmi(matrix A,long long n)
{
    matrix B;
    for(int i=0;i<=2;i++)
        B.mat[i][i]=1;
    while(n>0)
    {
        if(n&1) B=mul(A,B);
        A=mul(A,A);
        n=n/2;
    }
    return B;

}
double temp[10];int x[20];
int main()
{
    int n;double p;
    while(scanf("%d %lf",&n,&p)!=EOF)
    {
        for(int i=0;i<n;i++)
            scanf("%d",&x[i]);
        sort(x,x+n);
        if(n<1) {printf("1.0000000\n");continue;}
        matrix A;
        A.mat[0][0]=p,A.mat[0][1]=1.0-p;
        A.mat[1][0]=1.0;A.mat[1][1]=0;
        double ans=1.0;
        matrix B;temp[0]=p;temp[1]=1;
        int t=x[0];
        t--;
        if(t==0) {printf("0.0000000\n");continue;}
        else if(t==1) {ans=ans*(1.0-p);}
        else if(t==2) {ans=ans*p*(1-p);}
        else {
            matrix B=quickmi(A,t-2);
            double a1=temp[0]*B.mat[0][0]+temp[1]*B.mat[0][1],a2=temp[0];
            temp[0]=a1,temp[1]=a2;
            ans=ans*a1*(1-p);
        }
        temp[0]=ans;temp[1]=0;
        for(int i=1;i<n;i++)
        {
            t=x[i]-1;
            t=t-(x[i-1]+1);
            if(t<0) {ans=0;break;}//这里要注意不要掉了~
            B = quickmi(A,t);
            double a1=temp[0]*B.mat[0][0]+temp[1]*B.mat[0][1],a2=temp[0];
            temp[0]=a1,temp[1]=a2;
            ans=a1*(1-p);
            temp[0]=ans;temp[1]=0;
        }
        printf("%.7f\n",ans);
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值