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个雷,你从起点1号开始跳,有p的概率往前跳一步,有(1-p)的概率往前跳两步,如果碰到雷就会被炸死,问你安全的走完这段路的概率是多少。
思路:如果起点处有埋雷那么答案即为0,否则假设dp[i]表示安全到达到第i号格子时的概率,很容易想到dp方程,dp[i]=p*dp[i-1]+(1-p)*dp[i-2],dp[1]=1,dp[0]=0,所有有埋雷的格子概率都为0,假设最后一个雷所在格子编号为k,答案即为dp[k+1]。因为i很大,所以我们可以用矩阵快速幂来优化。
代码如下
#include <iostream>
#include <cstring>
#include <cstdio>
#include<algorithm>
using namespace std;
struct matrix
{
double x[2][2];
};
matrix mutimatrix(matrix a,matrix b)
{
matrix temp;
memset(temp.x,0,sizeof(temp.x));
for(int i=0;i<2;i++)
for(int j=0;j<2;j++)
for(int k=0;k<2;k++)
{
temp.x[i][j]+=a.x[i][k]*b.x[k][j];
//temp.x[i][j]%=mod;
}
return temp;
}
matrix k_powmatrix(matrix a,int n)
{
matrix temp;
memset(temp.x,0,sizeof(temp.x));
for(int i=0;i<2;i++)
temp.x[i][i]=1;
while(n)
{
if(n&1)
temp=mutimatrix(temp,a);
a=mutimatrix(a,a);
n>>=1;
}
return temp;
}
int x[15];
int main()
{
int n;
double p;
while(scanf("%d%lf",&n,&p)!=EOF)
{
for(int i=0;i<n;i++)
scanf("%d",&x[i]);
sort(x,x+n);
if(x[0]==1)
{
printf("0.0000000\n");
continue;
}
double P;//记录安全到达所埋雷的后一个位置的概率
for(int i=0;i<n;i++)
{
matrix st;
memset(st.x,0,sizeof(st.x));
st.x[0][0]=p;
st.x[0][1]=1;
st.x[1][0]=1-p;
st.x[1][1]=0;
matrix init;
memset(init.x,0,sizeof(init.x));
if(i!=0) init.x[0][0]=P;
else init.x[0][0]=1.0;
init.x[0][1]=0;
int len;
if(i!=0) len=x[i]-1-x[i-1]-1;
else len=x[i]-1-1;
if(len<0) //说明有两个雷的位置时挨在一起的,无法安全跳过
{
P=0;
break;
}
st=k_powmatrix(st,len);
st=mutimatrix(init,st);
P=st.x[0][0]*(1-p);//想要安全到达所埋雷的后一个位置,你需要在雷的前面一个位置上跳两步
}
printf("%.7f\n",P);
}
return 0;
}