您的位置:首页 > 其它

Poj 3744-Scout YYF I (概率dp+矩阵优化)

2017-07-18 15:28 337 查看
题目链接:

http://poj.org/problem?id=3744

题目大意:

一个人,一开始处于位置1,在n个位置上有地雷,不能接触,每次人有p概率向前走一步,有1−p概率向前跳两步,请问安全走过雷区的概率是多少,地雷位置x∈[1,100000000]

分析:

dp[i]表示走到i处的概率的话,可以很快推出

dp[i]=p∗dp[i−1]+(1−p)∗dp[i−2]

即dp[i]是由dp[i−1] 与dp[i−2]贡献得到,那么从1开始,向上不断贡献,遇到地雷位置跳过,然后走到a[n]+1位置的概率即是答案,但是根据题意a[n]+1过大,且有多组数据,所有需要优化。

可以发现在每段中,情况几乎都相同,而且dp转移式很自然的能想到斐波那契F[i]=F[i−1]+F[i−2] ,所以这题可以用矩阵快速幂计算每一段的概率值,下一段的起点即是之前一个地雷的下一个位置,分别计算不走到各地雷的概率并作积即可

注意:

地雷位置可以为1,即起点

地雷读入为乱序

地雷可能有重合

地雷之间可能连续,即出现2,3连续位置的地雷

代码:

#include<stdio.h>
#include<algorithm>
#include<iostream>
#include<string.h>
#include<math.h>
using namespace std;

typedef long long ll;

const int maxn = 207;
const int mod = 1000000007;
const int Mod = 1000;
struct mat{
int r,c;
double m[10][10];
mat(){}
mat(int _r,int _c):r(_r),c(_c){};
};

void init(mat &a){
memset(a.m,0,sizeof(a.m));
}

mat mul(mat a, mat b){
mat tmp(a.r,b.c);

for (int i = 1 ; i <= tmp.r; i ++)
{
for (int j = 1 ; j <= tmp.c ;j ++){
tmp.m[i][j] = 0;
for (int k =1 ; k <= a.c ; k ++){
tmp.m[i][j] = (tmp.m[i][j]+(a.m[i][k]*b.m[k][j]));
}
}
}
return tmp;
}

mat QP(mat a ,int n){
mat ans(a.r,a.r),tmp(a.r,a.r);
memcpy(tmp.m,a.m,sizeof(tmp.m));
init(ans);
for (int i = 1 ; i <= ans.r ; i ++)
{
ans.m[i][i] = 1;
}
while (n){
if (n&1)    ans = mul(ans,tmp);
n >>= 1;
tmp = mul(tmp,tmp);
}
return ans;
}

void print(mat a){
for (int i = 1 ; i <= a.r ;++ i){
for (int j = 1 ; j <= a.c ; ++j){
printf("%f",a.m[i][j]);
if (j==a.c) putchar('\n');
else  putchar(' ');
}
}
}

int n;
double p;
int arr[maxn];
double dp[100000009];

int main()
{
while (~scanf("%d%lf",&n,&p))
{
mat a(2,2);
a.m[1][1] = p;
a.m[1][2] = 1;
a.m[2][1] = 1-p;
a.m[2][2] = 0;
for (int i =1 ; i <= n ; i ++)
scanf("%d",&arr[i]);
sort(arr+1,arr+n+1);
if (arr[1] == 1)
printf("%.7f\n",0);
else
{
double t = 1;
mat ans = QP(a,arr[1]-1);
t *= (1-ans.m[1][1]);
int f = 1;
for (int i = 2 ; i <= n ; i ++)
{

if (arr[i]==arr[i-1])
continue;
if (arr[i]-arr[i-1]==1)
{
f = 0;
printf("%.7f\n",0);
break;
}
ans = QP(a,arr[i]-arr[i-1]-1)
af1c
;
t *= (1-ans.m[1][1]);
}
if (f)
printf("%.7f\n",t);
}

}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  dp