Maze HDU - 4035 hdu

題意:

一道過程很有趣的概率dp

在一棵樹上

你在節點1(根節點),

每個節點有一定概率k[i]被殺回到1號根節點,和一定概率e[i]逃離迷宮

還有剩下的概率往下一步走可以走向相鄰的任何節點

問離開迷宮走的步數的期望是多少?

思路:

這個題目和 ZOJ 3329 One Person Game(概率DP,求期望)一樣

每一部都是可以通過一定概率回到第一步的

即每一步的期望都有根節點期望的一部分


E[i]  =  ki * E[1]  + (1/m) *p[i]*(  (E[father]+1) + sigma(E[son]+1) )  m爲度數,p[i]=1-ki-ei,每次走一步+1,

E[i]  =  ki * E[1]  + (1/m) *p[i]*(  E[father] + sigma E[son]   )   +p[i]


按照套路 我們定義  E[i]  =  A[i] *E[1] + B[i]*E[father] +C[i];

帶入E[son]

E[i]  =  ki * E[1]  + (1/m) *p[i]*(  E[father] + sigma ( A[soni] *E[1] + B[soni]*E[i] +C[soni])   )   +p[i]

(1  -  p[i]/m*sigmaB[ison])E[i] =( k[i]+p[i]/m*sigma A[soni] )E[1] + (P[i]/m)*E[father] + (P[i]/m)* sigmaC[i] +p[i]

得出遞推公式

A[i] = ( k[i]+p[i]/m*sigma A[soni] ) / (1  -  p[i]/m*sigmaB[ison])

B[i] =                               (P[i]/m)  /  (1  -  p[i]/m*sigmaB[ison])

C[i]=((P[i]/m)* sigmaC[i] +p[i] ) / (1  -  p[i]/m*sigmaB[ison])


 E[1]  =  A[1] *E[1]  +C[1];

 E[1]  =C[1]/(1-A[1])


#include<bits/stdc++.h>
#define N 10009
const double eps=1e-9;  
using namespace std;
vector<int> son[N];
double p[N],k[N];
double A[N],B[N],C[N];
//A[i]=ki + pi/m *(sum A[son])
//B[i]=pi/m
//C[i]=pi/m sum(c[son]) +pi
//D = 1/(1-pi/m*sum[son])
bool dfs(int rt,int fa)
{
		double m=son[rt].size();
		A[rt]=k[rt];
		B[rt]=p[rt]/m;
		C[rt]=p[rt];
		double D=0;
		m=p[rt]/m;
		for(int i=0;i<son[rt].size();i++)
		{
			if(son[rt][i]==fa) continue;
 			if(!dfs(son[rt][i],rt)) return false;
			A[rt]+=(m*A[son[rt][i]]);
			C[rt]+=(m*C[son[rt][i]]);
			D+=(m*B[son[rt][i]]);
		}	
		
		if(fabs(1.0-D)<eps) return false;
			
	A[rt]/=(1.0-D);
	B[rt]/=(1.0-D);
	C[rt]/=(1.0-D);
	return true;
}
int main()
{
	int a,b,t,n;
	cin>>t;
	int kk=1;
	while(t--)
	{
		cin>>n;
		for(int i=1;i<=n;i++)
		son[i].clear();
		for(int i=1;i<n;i++)
		{
			scanf("%d%d",&a,&b);
			son[a].push_back(b);
			son[b].push_back(a);
		}
		for(int i=1;i<=n;i++)
		{
			scanf("%lf%lf",k+i,p+i);
			k[i]/=100.0;
			p[i]/=100.0;
			p[i]=1.0- k[i]  -p[i];
		}
		
		if(dfs(1,-1)&&fabs(A[1]-1.0)>eps)
		{
			double ans=C[1]/(1.0-A[1]);
		printf("Case %d: %.6lf\n",kk++,ans);
		}
		else
	    printf("Case %d: impossible\n",kk++);
	}
	return 0;
}




 



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章