poj2253 Frogger 克鲁斯卡尔变种算最小生成树最大边

本文详细解读了POJ2253题目的算法解决方案,包括使用克鲁斯卡尔算法来计算青蛙跳跃的最大距离。通过实例演示,帮助读者理解如何在给定石头坐标的情况下,找到青蛙从其初始位置到目标位置的最短跳跃路径。

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

POJ2253

Freddy青蛙坐在湖的中间。突然他发现,Fiona 青蛙坐在另一块。他计划去看望她,但由于水是脏的,他想避免游泳到达。

不幸的是,Fiona的石头超出了他的跳跃范围。因此,Freddy必须使用其他石头作为中间点。

因此他需要跳过很多块石头,很明显,他的最长跳跃距离应该要是相隔最长的两个石头的距离。

青蛙的距离被定义为在所有可能的路径之间的最长跳跃距离的最小值。

给定Freddy青蛙和Fiona青蛙所在石头的坐标,和其他石头的坐标,请计算青蛙距离。

 

输入格式

输入将包含一个或多个测试用例。每一个测试用例的第一行表示石头个数n(2<=n<=200)。接下来的n行每行包含两个整数xi,yi(0 <=xi,yi<= 1000)代表石头的坐标

第一行坐标是Freddy的石头,第二行坐标是Fiona的石头,剩下n-2行是其他石头的坐标。每一组测试案例间都有一个空行。N为0表示结束。

 

输出

每组测试数据输出两行,第一行输出Scenario #x,第二行输出Frog Distance = y,其中x为第几组测试数据,y表示青蛙距离,保留三位小数。最后请输出一个空行

 

样例输入

2

0 0

3 4

 

3

17 4

19 4

18 5

 

0

 

样例输出

Scenario#1

FrogDistance = 5.000

 

Scenario#2

FrogDistance = 1.414

 思路很简单,只是在做克鲁斯卡尔的时候不断地添加边,直到第一个点和第二个点被添加在一起,想想为什么这样就可以了??

#include<cstdio>
#include<algorithm>
#include<cstring>
#include<limits.h>
#include<iostream>
#include<math.h>
using namespace std;
struct edge{
	int x,y;
	double v;
}e[50001];
double map[205][205];
int x[205],y[205],cnt=0,f[50001];
double dis(int a,int b)
{
	return sqrt((x[a]*1.0-x[b]*1.0)*(x[a]*1.0-x[b]*1.0)+(y[a]*1.0-y[b]*1.0)*(y[a]*1.0-y[b]*1.0));
}
bool cmp(edge a,edge b)
{
	return a.v<b.v;
}
int find(int x)
{
	if(x!=f[x])f[x]=find(f[x]);
	return f[x];
}
int main()
{
	int n,num=0;
	while(cin>>n,n)
	{
		num++;
		memset(e,127,sizeof(e));
		int i,j,k=0;
		for(i=1;i<=n;i++)cin>>x[i]>>y[i];
		for(i=1;i<=n;i++)
			for(j=1;j<=n;j++)
				{
					map[i][j]=map[j][i]=dis(i,j);
					if(i<j)
					{
						e[++cnt].v=map[i][j];
				    	e[cnt].x=i;
				    	e[cnt].y=j;
					}
				}
		sort(e+1,e+1+cnt,cmp);
		for(i=1;i<=n;i++)f[i]=i;
		double d=0;
		for(i=1;i<=cnt;i++)
		{
			int fa=find(e[i].x),fb=find(e[i].y);
			if(fa!=fb)
			{
				k++;
				d=e[i].v;
				f[fa]=fb;
			}//在这之前都是克鲁斯卡尔的算法 
			if(find(1)==find(2))//精髓所在!自己体悟 
			{
				printf("Scenario #%d\nFrog Distance = %.3f\n\n",num,d);
				break;
			}
			if(k==n-1)break;
		}
	}
	return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值