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 /*
 2 POJ 3744
 3
 4 C++  0ms 184K
 5 */
 6 #include<stdio.h>
 7 #include<string.h>
 8 #include<algorithm>
 9 #include<iostream>
10 #include<math.h>
11 using namespace std;
12
13 struct Matrix
14 {
15     double mat[2][2];
16 };
17 Matrix mul(Matrix a,Matrix b)
18 {
19     Matrix ret;
20     for(int i=0;i<2;i++)
21       for(int j=0;j<2;j++)
22       {
23           ret.mat[i][j]=0;
24           for(int k=0;k<2;k++)
25             ret.mat[i][j]+=a.mat[i][k]*b.mat[k][j];
26       }
27     return ret;
28 }
29 Matrix pow_M(Matrix a,int n)
30 {
31     Matrix ret;
32     memset(ret.mat,0,sizeof(ret.mat));
33     for(int i=0;i<2;i++)ret.mat[i][i]=1;
34     Matrix temp=a;
35     while(n)
36     {
37         if(n&1)ret=mul(ret,temp);
38         temp=mul(temp,temp);
39         n>>=1;
40     }
41     return ret;
42 }
43
44 int x[30];
45 int main()
46 {
47     int n;
48     double p;
49     while(scanf("%d%lf",&n,&p)!=EOF)//POJ上G++要改为cin输入
50     {
51         for(int i=0;i<n;i++)
52           scanf("%d",&x[i]);
53         sort(x,x+n);
54         double ans=1;
55         Matrix tt;
56         tt.mat[0][0]=p;
57         tt.mat[0][1]=1-p;
58         tt.mat[1][0]=1;
59         tt.mat[1][1]=0;
60         Matrix temp;
61
62         temp=pow_M(tt,x[0]-1);
63         ans*=(1-temp.mat[0][0]);
64
65         for(int i=1;i<n;i++)
66         {
67             if(x[i]==x[i-1])continue;
68             temp=pow_M(tt,x[i]-x[i-1]-1);
69             ans*=(1-temp.mat[0][0]);
70         }
71         printf("%.7lf\n",ans);//POJ上G++要改为%.7f
72     }
73     return 0;
74 }
时间: 2024-10-06 16:56:31

poj 3744 概率dp+矩阵快速幂的相关文章

poj 3744 概率dp 矩阵快速幂优化

一位童子兵要穿过一条路,路上有些地方放着地雷.这位童子兵非常好玩,走路一蹦一跳的.每次他在 i 位置有 p 的概率走一步到 i+1 ,或者 (1-p) 的概率跳一步到 i+2.童子兵初始在1位置,求他安全通过这条道路的概率. 以所在位置为状态,dp[i] 表示在位置 i 的安全的概率. dp[i] = p * dp[i-1] + (1 - p) * dp[i-2]; // i 位置没有地雷 但是题目数据的范围是 10^8 这样dp的话会 TLE. 想想可以用矩阵快速幂优化.简单退出矩阵是 |p

Scout YYF I POJ - 3744(概率dp + 矩阵快速幂)

题意: 一条路上有n个地雷,你从1开始走,单位时间内有p的概率走一步,1-p的概率走两步,问安全通过这条路的概率 解析: 很容易想到 dp[i] = p * dp[i-1] + (1 - p) * dp[i]; 然而...t,但这个式子明显可以用矩阵快速幂加个氮气一下加速一下... 把所有的点输入之后 sort一下,那么就能把这条路分成很多段 每一段以地雷为分界线 1 - x[0]  x[0]+1 - x[1]  x[1]+1 - x[2] ````````` 然后求出安全通过每一段的概率  

POJ 3744 Scout YYF I (概率DP+矩阵快速幂)

题意:小明要从1走过一段直线雷区,给定n个地雷的坐标,他走一步的概率是p,两步的概率为1-p,问你他能安全通过雷区的概率. 析:很明显这是一个概率DP,用d(i)表示到达 i 时他安全的概率,那么d[i] = p * d[i-1] + (1-p) * d[i-2];这个状态转移方程很好理解, 就是说要想到达 i 要么从第 i-1 走一步,要么从 i-2 走两步,最后加起来,然后问题来了,这个数可能达到 1E8,那么时间空间复杂度都受不了, 观察这个状态转移方程,是不是很像Fibnacci数列,所

poj 3744 Scout YYF I (概率DP+矩阵快速幂)

Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 5062   Accepted: 1370 Description YYF is a couragous scout. Now he is on a dangerous mission which is to penetrate into the enemy's base. After overcoming a series difficulties, YYF is now

POJ3744——概率DP 矩阵快速幂优化——Scout YYF I

http://poj.org/problem?id=3744 矩阵快速幂: 利用DP的递推式 就本题来说 dp[i] = p*dp[i-1] + (1-p)*dp[i-2] 由于x非常大最大1亿,这样的话复杂度就为1亿 所以这里可以用矩阵的思想 [dp[i]   dp[i-1] ] = [ dp[i-1]  dp[i-2] ] | p   1 - p| | 1      0  | 递推得到 n - 1 [dp[n]   dp[n-1]] = [dp[1]   dp[2] ] |p   1 - p

[poj3744]Scout YYF I(概率dp+矩阵快速幂)

题意:在一维空间上存在一些雷,求安全通过的概率.其中人有$p$的概率前进一步,$1-p$的概率前进两步. 解题关键:若不考虑雷,则有转移方程:$dp[i] = p*dp[i - 1] + (1 - p)*dp[i - 2]$ 由于雷的数量很少,所以可以以雷为界,将区域分开,在每个区域中,通过该段的概率等于1-踩到该段终点的地雷的概率.然后用矩阵快速幂优化一下即可 1 #include<cstdio> 2 #include<cstring> 3 #include<algorit

(POJ 3744)Scout YYF I(概率dp+矩阵快速幂)

概率dp入门题,转移方程为dp[i]=dp[i-1]*p+dp[i-2]*(1-p) 因为n个数字上限很大,所以常规的概率dp基本不可能,要用矩阵优化. 把路程分成n+1段,分别计算通过每段的成功率,即刚好跨越地雷的概率(dp[地雷x+1]) 算好每段之后把每段的成功率相乘. (若有两颗地雷相邻那么成功率是0) #include<iostream> #include<cstdio> #include<vector> #include<set> #includ

POJ-3744ScoutYYFI[概率DP][矩阵快速幂]

534禄DTJ蓝厍7簿L返http://www.zcool.com.cn/collection/ZMTgyMzIyNzI=.html 未导IU48lXF侥渍幕http://www.zcool.com.cn/collection/ZMTgyMzIzNjA=.html O1k澳4匀siy扯饲uhttp://www.zcool.com.cn/collection/ZMTgyMzIzODg=.html G3U8w2cs0y2http://www.zcool.com.cn/collection/ZMTgy

poj 2778 AC自动机 + 矩阵快速幂

// poj 2778 AC自动机 + 矩阵快速幂 // // 题目链接: // // http://poj.org/problem?id=2778 // // 解题思路: // // 建立AC自动机,确定状态之间的关系,构造出,走一步 // 能到达的状态矩阵,然后进行n次乘法,就可以得到状态间 // 走n步的方法数. // 精髓: // 1):这个ac自动机有一些特别,根节点是为空串,然而 // 每走一步的时候,如果没法走了,这时候,不一定是回到根 // 节点,因为有可能单个的字符时病毒,这样