您的位置:首页 > 其它

POJ3744:Scout YYF I(概率dp & 矩阵优化)

2017-07-15 14:32 369 查看
Scout YYF I

Time Limit: 1000MS Memory Limit: 65536K
Total Submissions: 8867 Accepted: 2599
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

Source

POJ Monthly Contest - 2009.08.23, Simon

题意:x轴上,主角在1的位置,给N个地雷的坐标,以及主角向前走1步的概率为p和向前走2步的概率1-p,问主角能安全通过所有地雷的概率。

思路:dp[i]为安全到达i的概率,易得dp[i] = p*dp[i-1]+(1-p)*dp[i-2],但是地雷的地方不能走,所以将路程分成若干段,每段的起点为上一个地雷的下一位,终点为地雷,所以每段只有一个地雷,算得每段安全通过的概率(1-踩中地雷的概率)再乘法原理乘起来就是答案,但是N很大,需要用矩阵连乘来优化,dp[1]=1,



# include <iostream>
# include <cstdio>
# include <cstring>
# include <algorithm>
using namespace std;
int a[13];
struct Mat{double mat[2][2];};

Mat operator *(Mat a, Mat b)
{
Mat c;
for(int i=0; i<2; ++i)
{
for(int j=0; j<2; ++j)
{
c.mat[i][j] = 0;
for(int k=0; k<2; ++k)
{
c.mat[i][j] += a.mat[i][k]*b.mat[k][j];
}
}
}
return c;
}

Mat operator ^(Mat a, int k)
{
Mat c;
for(int i=0; i<2; ++i)
for(int j=0; j<2; ++j)
c.mat[i][j] = (i==j);
for(;k;k>>=1)
{
if(k&1) c=c*a;
a=a*a;
}
return c;
}
int main()
{
int n;
double p;
while(~scanf("%d%lf",&n,&p))
{
a[0] = 0;
Mat t;
t.mat[0][0] = p;
t.mat[0][1] = 1-p;
t.mat[1][0] = 1;
t.mat[1][1] = 0;
for(int i=1; i<=n; ++i) scanf("%d",&a[i]);
sort(a+1,a+n+1);
double ans = 1;
for(int i=1; i<=n; ++i)
ans = ans*(1-(t^(a[i]-a[i-1])).mat[1][0]);
printf("%.7f\n",ans);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: