【最短路变形】偷懒路径

【题目描述】

呆子打算去上自习,虽然他不愿意。他来到五教门口时,发现他来迟了,事先又没有占位子,可能没有位子了。
根据经验,他知道每个小教室有位子的概率为p1,每个梯形教室有位子的概率为p2,每个扇形教室有位子得概率为p3。
由于他并不是真的想上自习,所以他并不打算到每个教室去找位子,而是选一条从前门走到后门的路径,路过一个教室就进去看看,如果有位子就只好自习,如果没有就继续向前,直到后门还没有找到位子就回去睡觉。
现在他希望你替他找到一条路径,使得他回去睡觉的概率最大。

【输入格式】

输入的第一行是1个整数n ( 1<=n<=100 ),表示五教共有n个教室,编号为1,2,3 ... n。
第2行是三个实数p1 p2 p3 ( 0 <= p1 p2 p3 <=1,精度为0.01 )。
第3到2+n为一列整数:
i c s1 s2 m a1 a2 a3 .... am
其中 i为教室编号。
c 的值为0,1或2,分别表示i号教室为小/梯形/扇形教室。
若i号教室与前门直接相邻,则s1=1,否则s1=0。
若i号教室与后门直接相邻,则s2=1,否则s2=0。
a1 a2 ..... am 是与第i个教室直接相邻的教室编号。
所谓直接相邻,是指两个教室之间或大门与教室之间存在一条不经过其他教室或大门的路。
保证至少存在一条从前门到后门的道路

【输出格式】

输出一行,包含一个实数,表示呆子回去睡觉的最大概率。四舍五入到0.01。


题目很长,其实就是求一条最长路

对于所有直接与前门相连的点,我们都先丢入队列,概率为该教室没有座位的概率

跑一次最长路,最后查询所有与后门直接相连的教室的最大概率

#include<iostream>
#include<iomanip>
#include<cstdio>
#include<cstring>
#include<queue>
using namespace std;
int n,c[105],a[105][105],s[105],s2[105];
double p[3],f[105],ans;
bool vis[105];
queue<int> q;
int main()
{
	scanf("%d",&n);
	scanf("%lf%lf%lf",&p[0],&p[1],&p[2]);
	for(int i=1;i<=n;i++)
	{
		int x;
		scanf("%d",&x);
		scanf("%d",&c[x]);
		scanf("%d%d",&s[x],&s2[x]);
		scanf("%d",&a[x][0]);
		for(int j=1;j<=a[x][0];j++) scanf("%d",&a[x][j]);
	}
	for(int i=1;i<=n;i++) if(s[i]) q.push(i),vis[i]=1,f[i]=1-p[c[i]];
	while(!q.empty())
	{
		int u=q.front();
		q.pop();
		vis[u]=0;
		for(int i=1;i<=a[u][0];i++)
		{
			if(f[u]*(1-p[c[a[u][i]]])>f[a[u][i]])
			{
				f[a[u][i]]=f[u]*(1-p[c[a[u][i]]]);
				if(!vis[a[u][i]]) q.push(a[u][i]);
			}
		}
	}
	for(int i=1;i<=n;i++) if(s2[i]) ans=max(ans,f[i]);
	printf("%0.2lf",ans);
}

猜你喜欢

转载自blog.csdn.net/Dy_Dream/article/details/83013298