poj-3744 Scout YYF I [用矩阵优化概率递推式]

/*
题意:在一条不满地雷的路上,你现在的起点在1处。
在N个点处布有地雷,1<=N<=10。地雷点的坐标范围:[1,100000000].
每次前进p的概率前进一步,1-p的概率前进两步。
问顺利通过这条路的概率。就是不要走到有地雷的地方。

dp[i] 表示走到i的概率
dp[i+1]=dp[i]*p+dp[i-1]*(1-p); 

用矩阵快速幂优化
递推式转矩阵 
| 0    1| |dp(k-1)|  = |  dp(k) | 
| 1-p  p| | dp(k) |    | dp(k+1)| 
dp[0]=0,dp[1]=1;
设x[i] 表示第i个地雷的位置
把道路分成开
1~x[1] x[1]+1~x[2]...... x[n-1]+1~x[n]
对于每一段  sus[i] 表示 x[i-1]+1~x[i]-1这一段没有挂掉
那么sus[i]= 1-从x[i-1]+1刚好走到x[i]的概率;
那么 ans为sus[i]的总乘积(即每一段都没屎) 
*/ 
#include <stdio.h>
#include <algorithm>
#include <vector>
using namespace std;
typedef vector<double> vec;
typedef vector<vec> mat;
const int maxn=30;
const double eps=1E-8; 
int x[maxn];
int n;
double p;
mat mul(const mat &a,const mat &b)
{
	mat c(2,vec(2,0));
	for(int i=0;i<2;++i)
		for(int j=0;j<2;++j)
			for(int k=0;k<2;++k)
				c[i][j]+=a[i][k]*b[k][j];
	return c;
}
double T(int k)
{
	double s[2][2]={{0,1},{1-p,p}};
	mat A(2,vec(2));
	mat p(2,vec(2,0));
	p[0][0]=p[1][1]=1;
	for(int i=0;i<2;++i)
		for(int j=0;j<2;++j)
			A[i][j]=s[i][j];
	while(k>0)
	{
		if(k&1)
			p=mul(A,p);
		k=k>>1;
		A=mul(A,A);
	}
	return  p[1][1];
}
void DP()
{
	double ans=1;
	double tmp=T(x[1]-1);
	ans*=(1-tmp);
	for(int i=2;i<=n;++i)
	{
		if(x[i]==x[i-1]) continue;
		tmp=1-T(x[i]-x[i-1]-1);
		ans*=tmp;
	}
	printf("%.7f\n",ans<eps?0:ans);
}
int main()
{
	while(~scanf("%d %lf",&n,&p))
	{
		for(int i=1;i<=n;++i)
			scanf("%d",x+i);
		sort(x+1,x+1+n);
		DP();
	}
	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值