POJ 3744 Scout YYF I

算概率dp吗?算普通概率题。。。

不过做起来越发感觉,,,我应该回高中补概率去了。。

谁特么说的语数外物化生以后没用的!!!!不过物化生还真么多大用,,相对来说史地政更有用一些,写个入党申请书什么的大笑大笑

陷阱把直线分成了若干段,每一段都是安全的,求出通过这一段的概率,乘上跨过陷阱的概率,再乘下一段的概率就行了。

具体来说,对于某一段长度为nk的线段k,设a是线段k的开头,b是线段k的结尾,nk=a-b-1,

到达a的概率设为1,到达a+1概率是p,到达a+2的概率就是Pa*(1-p)+Pa+1*p,这样就可以递推了。

由于Pam=Pam-1*p+Pam-2*(1-p),即推的公式都是一样的,可以用矩阵乘法+快速幂来做。

问题的解可以看做Pn1*(1-p)*Pn2*(1-p)*....Pnn*(1-p),因为最后一个陷阱要跳过去才安全。

代码:

#include<stdio.h>
#include<algorithm>
using namespace std;
int x[20];
double a,b,c,d,p;
void cheng(double x[3][3],double y[3][3]){
	a=x[1][1]*y[1][1]+x[1][2]*y[2][1];
	b=x[1][1]*y[1][2]+x[1][2]*y[2][2];
    c=x[2][1]*y[1][1]+x[2][2]*y[2][1];
	d=x[2][1]*y[1][2]+x[2][2]*y[2][2];
	x[1][1]=a;x[1][2]=b;x[2][1]=c;x[2][2]=d;
}
double chengfang(int n){
	double a[3][3],b[3][3];
	a[1][1]=1;a[1][2]=p;  a[2][1]=0;a[2][2]=0;
	b[1][1]=0;b[1][2]=1-p;b[2][1]=1;b[2][2]=p;
	while(n){
		if(n&1)cheng(a,b);
		cheng(b,b);n>>=1;
	}
	return a[1][1];
}
int main(){
	int i,n;
	double as;
	while(~scanf("%d%lf",&n,&p)){
		for(i=1;i<=n;i++)
		    scanf("%d",&x[i]);
		as=1;sort(x+1,x+n+1);
		for(i=1;i<=n;i++){
		    if(x[i]==x[i-1])continue;
		    if(x[i]==x[i-1]+1)break;
		    as*=chengfang(x[i]-x[i-1]-2)*(1-p);
		}
		printf("%.7lf\n",i<=n?0:as);
	}
	return 0;
}


你可能感兴趣的:(概率DP)