Maze HDU - 4035 hdu

本文介绍了一种利用概率动态规划解决迷宫中逃离期望步数的问题。在一个树形结构的迷宫中,玩家从根节点出发,面对被杀回起点、成功逃离及继续探索的概率挑战,通过构建数学模型求解最优期望。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题意:

一道过程很有趣的概率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;
}




 



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值