Poj 3744 Scout YYF I (概率DP 矩阵优化)

来源:互联网 发布:刷步数软件 编辑:程序博客网 时间:2024/04/29 21:03

Scout YYF I
Time Limit: 1000MS Memory Limit: 65536KTotal Submissions: 4857 Accepted: 1290

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 at the start of enemy's famous "mine road". This is a very long road, on which there are numbers of mines. At first, YYF is at step one. For each step after that, YYF will walk one step with a probability of p, or jump two step with a probality of 1-p. Here is the task, given the place of each mine, please calculate the probality that YYF can go through the "mine road" safely.

Input

The input contains many test cases ended with EOF.
Each test case contains two lines.
The First line of each test case is N (1 ≤ N ≤ 10) and p (0.25 ≤ p ≤ 0.75) seperated by a single blank, standing for the number of mines and the probability to walk one step.
The Second line of each test case is N integer standing for the place of N mines. Each integer is in the range of [1, 100000000].

Output

For each test case, output the probabilty in a single line with the precision to 7 digits after the decimal point.

Sample Input

1 0.522 0.52 4

Sample Output

0.50000000.2500000

今天学习概率DP,感觉主要就是对全概率公式的运用,期望的计算进行了一个学习,最重要的还是写出状态方程。一般期望都需要逆着推,概率正着推。这道题就是一道求概率的题。乍一看其实很简单,状态方程很容易想到,dp[i] = p*dp[i-1]+(1-p)*dp[i];

但是数据非常大,一个是数组开不下,另一个是会超时。被教育了一下,说是要用矩阵优化,于是学习了一下矩阵优化的原理。


矩阵优化:利用矩阵的特点,对一些递推式进行优化,举个例子:



本题的状态方程就可以表示成这样,所以到最后可以写成矩阵的n次方,这时候就可以使用矩阵的快速幂算法,复杂度是O(N^3 * logM)的。针对本题,可以只针对地雷的位置进行规划,求出一定会踩地雷的概率,再减掉。最终把各段的概率相乘就是答案。

代码如下:

#include <iostream>#include <cstdio>#include <cstring>#include <algorithm>using namespace std;const int N = 2;int n;struct Mat{    double mat[N][N];    Mat operator * (Mat b)    {        Mat c;        memset(c.mat,0,sizeof(c.mat));        for(int i=0; i<N; i++)            for(int j=0; j<N; j++)            {                for(int k=0; k<N; k++)                    c.mat[i][j]+=mat[i][k]*b.mat[k][j];            }        return c;    }    friend Mat operator ^ (Mat a,int k)    {        Mat c;        for(int i = 0; i<N; i++)            for(int j=0; j<N; j++)                c.mat[i][j]=(i==j);        for(; k; k>>=1)        {            if(k&1)c = c*a;            a = a*a;        }        return c;    }};double p;int pos[15];int main(){    Mat x,t;    while(scanf("%d%lf",&n,&p)==2){        for(int i=1;i<=n;i++)scanf("%d",pos+i);        sort(pos+1,pos+n+1);        double ans = 1;        if(pos[0] == 1){printf("%.7lf\n",0.0);continue;}        x.mat[0][0] = p;        x.mat[0][1] = 1-p;        x.mat[1][0] = 1;        x.mat[1][1] = 0;        for(int i=1;i<=n;i++)        {            if(pos[i]-pos[i-1]==0)                continue;            t = x^(pos[i]-pos[i-1]-1);            //printf("tttt: %lf\n",t.mat[0][0]);            ans*=(1-t.mat[0][0]);        }        printf("%.7lf\n",ans);    }    return 0;}








0 0
原创粉丝点击