• poj 3744 概率dp+矩阵快速幂


    题意:在一条布满地雷的路上,你现在的起点在1处。在N个点处布有地雷,1<=N<=10。地雷点的坐标范围:[1,100000000].
    每次前进p的概率前进一步,1-p的概率前进1-p步。问顺利通过这条路的概率。就是不要走到有地雷的地方。
    链接:点我
     
    设dp[i]表示到达i点的概率,则 初始值 dp[1]=1.
    很容易想到转移方程: dp[i]=p*dp[i-1]+(1-p)*dp[i-2];
    但是由于坐标的范围很大,直接这样求是不行的,而且当中的某些点还存在地雷。
     
     
    N个有地雷的点的坐标为 x[1],x[2],x[3]```````x[N].
    我们把道路分成N段:
    1~x[1];
    x[1]+1~x[2];
    x[2]+1~x[3];
    `
     
    x[N-1]+1~x[N].
     
    转移矩阵:
      dp[i]    | p ,1-p  |    dp[i-1]
                =|            |*
    dp[i-1]   | 1 , 0    |   dp[i-2]
     
    这样每一段只有一个地雷。我们只要求得通过每一段的概率。乘法原理相乘就是答案。
    对于每一段,通过该段的概率等于1-踩到该段终点的地雷的概率。
     
    就比如第一段 1~x[1].  通过该段其实就相当于是到达x[1]+1点。那么p[x[1]+1]=1-p[x[1]].
    但是这个前提是p[1]=1,即起点的概率等于1.对于后面的段我们也是一样的假设,这样就乘起来就是答案了。
     
    对于每一段的概率的求法可以通过矩阵乘法快速求出来。
     
     1 #include<cstdio>
     2 #include<iostream>
     3 #include<algorithm>
     4 #include<cstring>
     5 #include<cmath>
     6 #include<queue>
     7 #include<map>
     8 using namespace std;
     9 #define MOD 1000000007
    10 const int INF=0x3f3f3f3f;
    11 const double eps=1e-5;
    12 typedef long long ll;
    13 #define cl(a) memset(a,0,sizeof(a))
    14 #define ts printf("*****
    ");
    15 const int MAXN=1005;
    16 int n,m,tt,x[MAXN],dp[MAXN];
    17 struct Matrix
    18 {
    19     double mat[2][2];
    20 };
    21 Matrix mul(Matrix a,Matrix b)
    22 {
    23     Matrix ret;
    24     for(int i=0;i<2;i++)
    25       for(int j=0;j<2;j++)
    26       {
    27           ret.mat[i][j]=0;
    28           for(int k=0;k<2;k++)
    29             ret.mat[i][j]+=a.mat[i][k]*b.mat[k][j];
    30       }
    31     return ret;
    32 }
    33 Matrix pow_M(Matrix a,int n)
    34 {
    35     Matrix ret;
    36     memset(ret.mat,0,sizeof(ret.mat));
    37     for(int i=0;i<2;i++)ret.mat[i][i]=1;
    38     Matrix temp=a;
    39     while(n)
    40     {
    41         if(n&1)ret=mul(ret,temp);
    42         temp=mul(temp,temp);
    43         n>>=1;
    44     }
    45     return ret;
    46 }
    47 int main()
    48 {
    49     int i,j,k;
    50     #ifndef ONLINE_JUDGE
    51     freopen("1.in","r",stdin);
    52     #endif
    53     double p;
    54     while(scanf("%d%lf",&n,&p)!=EOF)
    55     {
    56         double ans=1;
    57         for(i=0;i<n;i++)    scanf("%d",x+i);
    58         sort(x,x+n);
    59         Matrix a,b;
    60         a.mat[0][0]=p;
    61         a.mat[0][1]=1-p;
    62         a.mat[1][0]=1;
    63         a.mat[1][1]=0;
    64         b=pow_M(a,x[0]-1);
    65         ans*=(1-b.mat[0][0]);
    66         for(i=1;i<n;i++)
    67         {
    68             if(x[i]==x[i-1])    continue;
    69             b=pow_M(a,x[i]-x[i-1]-1);
    70             ans*=(1-b.mat[0][0]);
    71         }
    72         printf("%.7f
    ",ans);
    73     }
    74 }
  • 相关阅读:
    002.NFS相关配置项
    001.NFS简介
    002.DNS-BIND简介
    001.DNS原理及配置格式
    002.DHCP配置
    001.DHCP简介
    001.Chrony时间服务器
    博客开篇记载!
    【python-opencv】图像梯度
    【python-opencv】形态转换
  • 原文地址:https://www.cnblogs.com/cnblogs321114287/p/4400949.html
Copyright © 2020-2023  润新知