poj3744 Scout YYF I

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.5
2
2 0.5
2 4

Sample Output

0.5000000
0.2500000

题目大意:一条路上有n个雷,位置分别为ai,从1开始做,p的概率走一步,1-p的概率走两步。请问活着走出这条路的几率。
思路:

f[i]表示在没有地雷的情况下,走i距离的几率

可得f[i]=f[i-1]*p+f[i-2]*(1-p)

类似斐波那契的一个公式

构造一个矩阵

  0  1      的i次发   X          0

1-p p                                1

因为步数比较多,必须用快速幂。

 

所以ans×=1-f    ,f是从上个雷走到这个雷的概率

/*
 * Author:  Joshua
 * Created Time:  2014年05月24日 星期六 14时28分06秒
 * File Name: poj3744.cpp
 */
#include<cstdio>

typedef long long LL;
int n;

void solve()
{
    double pp,ans=1;
    int a[11],temp;
    scanf("%lf",&pp);
    for (int i=1;i<=n;++i)
        scanf("%d",&a[i]);
    double mat[2][2];
    mat[0][0]=0;
    mat[0][1]=1;
    mat[1][0]=1-pp;
    mat[1][1]=pp;

    for (int i=1;i<=n;++i)
        for (int j=i+1;j<=n;++j)
            if (a[i]>a[j])
            {
                temp=a[i];
                a[i]=a[j];
                a[j]=temp;
            }
    a[0]=0;
    double mm[2][2];
    double c[2];
    for (int tt=1;tt<=n;++tt)
    {
        double mm[2][2],tm[2][2];
        for (int i=0;i<=1;++i)
            for (int j=0;j<=1;++j)
                tm[i][j]=mat[i][j];
        c[0]=0;
        c[1]=1;
        int k=a[tt]-a[tt-1];
        while (k)
        {
            for (int i=0;i<=1;++i)
                for(int j=0;j<=1;++j)
                    mm[i][j]=tm[i][j];
            if (k&1)
            {
                double a,b;
                a=c[0]*mm[0][0]+c[1]*mm[0][1];
                b=c[0]*mm[1][0]+c[1]*mm[1][1];
                c[0]=a;
                c[1]=b;
            }
            for (int i=0;i<=1;++i)
                for (int j=0;j<=1;++j)
                {
                    tm[i][j]=0;
                    for (int l=0;l<=1;++l)
                        tm[i][j]+=mm[i][l]*mm[l][j];
                }
            k>>=1;
        }
        ans*=1-c[0];
    }
    printf("%.7f\n",ans);
}
int main()
{
    while (~scanf("%d",&n))
    {
        solve(); 
    }
    return 0;
}

 

posted @ 2014-05-25 12:44  一个大叔  阅读(176)  评论(0编辑  收藏  举报