1. 程式人生 > >【最短路變形】偷懶路徑

【最短路變形】偷懶路徑

【題目描述】

呆子打算去上自習,雖然他不願意。他來到五教門口時,發現他來遲了,事先又沒有佔位子,可能沒有位子了。 根據經驗,他知道每個小教室有位子的概率為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);
}