zoukankan      html  css  js  c++  java
  • poj 3744 Scout YYF I (矩阵快速幂 优化 概率dp)

    题目链接

    分析&&题意来自 : http://www.cnblogs.com/kuangbin/archive/2012/10/02/2710586.html

    题意:

    在一条不满地雷的路上,你现在的起点在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].
     
    这样每一段只有一个地雷。我们只要求得通过每一段的概率。乘法原理相乘就是答案。
    对于每一段,通过该段的概率等于1-踩到该段终点的地雷的概率。
     
    就比如第一段 1~x[1].  通过该段其实就相当于是到达x[1]+1点。那么p[x[1]+1]=1-p[x[1]].
    但是这个前提是p[1]=1,即起点的概率等于1.对于后面的段我们也是一样的假设,这样就乘起来就是答案了。
     
    对于每一段的概率的求法可以通过矩阵乘法快速求出来。
    ---------------------------------------------------------------------------------------------------
     
    我用的矩阵| 0 ,1-P |  ,开始的为|1, p|, 乘以这个矩阵x[i] - 1次,就可以得到该点的概率。
                  | 1 ,   p |
     1 #include <iostream>
     2 #include <cstdio>
     3 #include <cstring>
     4 #include <cstdlib>
     5 #include <queue>
     6 #include <cmath>
     7 #include <algorithm>
     8 #define LL __int64
     9 const int maxn = 100+10;
    10 using namespace std;
    11 
    12 struct node
    13 {
    14     double m[3][3];
    15 };
    16 
    17 node mul(node a, node b) //两个矩阵想乘
    18 {
    19     int i, j, k;
    20     node c;
    21     for(i = 0; i < 2; i++)
    22     for(j = 0; j < 2; j++)
    23     {
    24         c.m[i][j] = 0;
    25         for(k = 0; k < 2; k++)
    26         c.m[i][j] += a.m[i][k]*b.m[k][j];
    27     }
    28     return c;
    29 }
    30 node pow_n(node a, int n) //a矩阵乘n次
    31 {
    32     node c;
    33     memset(c.m, 0, sizeof(c.m));
    34     for(int i = 0; i < 2; i++) c.m[i][i] = 1;
    35 
    36     while(n)
    37     {
    38         if(n%2)
    39         c = mul(c, a);
    40 
    41         a = mul(a, a);
    42         n /= 2;
    43     }
    44     return c;
    45 }
    46 int main()
    47 {
    48     int n, i, x[20], pre;
    49     double p, ans;
    50     while(~scanf("%d%lf", &n, &p))
    51     {
    52         node a;
    53         ans = 1.0;
    54         a.m[0][0] = 0; a.m[0][1] = 1.0-p;
    55         a.m[1][0] = 1.0; a.m[1][1] = p;
    56         for(i = 0; i < n; i++)
    57         scanf("%d", &x[i]);
    58         sort(x, x+n);
    59 
    60         pre = 0;
    61         for(i = 0; i < n; i++)
    62         {
    63             node tmp = pow_n(a, x[i]-pre-1);
    64             ans *= (1.0-(1.0*tmp.m[0][0]+p*tmp.m[1][0]));
    65             pre = x[i];
    66         }
    67         printf("%.7f
    ", ans);
    68     }
    69     return 0;
    70 }
     
  • 相关阅读:
    后可视化编程
    查看图片前进后退效果图
    [置顶] 后可视化编程
    xCAT安装配置文档
    jQuery邮箱验证
    2011级csdnjava张侃—Spring(1)
    [置顶] 后可视化编程时代
    php中Session使用方法详解
    关于浏览器ip代理导致定位错乱问题的坑
    PHPStorm使用技巧及快捷键
  • 原文地址:https://www.cnblogs.com/bfshm/p/4060646.html
Copyright © 2011-2022 走看看