青蛙 POJ - 2253(变形最短路)

青蛙 POJ - 2253

弗雷迪青蛙坐在湖中央的一块石头上。突然他注意到坐在另一块石头上的Fiona Frog。他打算去看望她,但由于水很脏,而且到处都是游客的防晒霜,他不想游泳,而是通过跳跃来接触她。
不幸的是,Fiona 的石头超出了他的跳跃范围。因此,弗雷迪考虑使用其他石头作为中间停靠点,并通过几次小跳跃的顺序到达她。
要执行给定的跳跃序列,青蛙的跳跃范围显然必须至少与序列中发生的最长跳跃一样长。
因此,两块石头之间的青蛙距离(人类也称为最小最大距离)被定义为两块石头之间所有可能路径上的最小必要跳跃范围

您将获得 Freddy 的石头、Fiona 的石头和湖中所有其他石头的坐标。你的工作是计算 Freddy 和 Fiona 的石头之间的青蛙距离。
输入
输入将包含一个或多个测试用例。每个测试用例的第一行将包含石头的数量 n (2<=n<=200)。接下来的 n 行每行包含两个整数 xi,yi (0 <= xi,yi <= 1000),代表石头 #i 的坐标。石头#1 是Freddy 的石头,石头#2 是Fiona 的石头,其他n-2 块石头是空的。每个测试用例后面都有一个空行。输入以 n 的零 (0) 值终止。
输出
对于每个测试用例,打印一行“Scenario #x”和一行“Frog Distance = y”,其中 x 由测试用例编号(它们从 1 开始编号)替换,y 由适当的实数替换,打印到小数点后三位。在每个测试用例之后放置一个空行,甚至在最后一个之后。
样本输入
2
0 0
3 4

3
17 4
19 4
18 5

0
样本输出
场景#1
青蛙距离 = 5.000

场景#2
青蛙距离 = 1.414
题意:求Freddy 在的石头1到Fiona的石头2的最终距离最短,并且在过程中需要跳跃两块石头的最大的间距, 如果有多条路,那最大的间距间就要选择最小的
思路:用dis[i]保存的是起点到i点过程需要跳跃的最大距离。
Floyd算法

#include<iostream>
#include<cstring>
#include<cmath>
#include<algorithm>
using namespace std;
int n;
struct node{
	double x;
	double y;
}dian[300];
double dis[250][250];
void floyd()
{
	int i,j,k;
	for(k=1;k<=n;k++){
		for(i=1;i<=n;i++){
			for(j=1;j<=n;j++){
				dis[i][j]=min(dis[i][j],max(dis[i][k],dis[k][j]));//重点
			}
		}
	}
}
int main()
{
	int time=0,i,j;
	while(cin>>n&&n){
		for(i=1;i<=n;i++){
			scanf("%lf%lf",&dian[i].x,&dian[i].y);
		}
		for(i=1;i<=n;i++){//计算每2个点之间的距离
			for(j=i+1;j<=n;j++){
				dis[i][j]=dis[j][i]=sqrt((dian[i].x-dian[j].x)*(dian[i].x-dian[j].x)+(dian[i].y-dian[j].y)*(dian[i].y-dian[j].y));//注意dis[i][j]==dis[j][i]双向
			}
		}
		floyd();
		printf("Scenario #%d\nFrog Distance = %.3lf\n\n",++time,dis[1][2]);//输出1,到2的过程最大距离最小
	}
}

SPFA

#include<iostream>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<queue>
#include<climits>
using namespace std;
int n;
double inf=INT_MAX;
struct node{
	double x;
	double y;
}dian[300];
double dis[500];
double e[250][250];
int vist[250];
void SPFA()
{
	fill(dis,dis+500,inf);
	memset(vist,0,sizeof(vist));
	dis[1]=0;//初始化起点的距离为1 
	queue<int> q;//SPFA的队列只需装一个点 
	q.push(1);//起始点1入队 
	vist[1]=1;//入队标记 
	while(!q.empty()){
		
		int cur=q.front();
		q.pop();
		vist[cur]=0;//出队标记 
		for(int i=1;i<=n;i++){//枚举每一个点 
			if(dis[i]>max(dis[cur],e[cur][i])){
				dis[i]=max(dis[cur],e[cur][i]);//更新数据 
				if(!vist[i]){//如果已经在队列里就不要压入了 
					q.push(i);
					vist[i]=1;
				}
			}
		}
	}
} 
int main()
{
	int time=0,i,j;
	while(cin>>n&&n){
		for(i=1;i<=n;i++){
			scanf("%lf%lf",&dian[i].x,&dian[i].y);
		}
		for(i=1;i<=n;i++){
			for(j=i+1;j<=n;j++){
				e[i][j]=e[j][i]=sqrt((dian[i].x-dian[j].x)*(dian[i].x-dian[j].x)+(dian[i].y-dian[j].y)*(dian[i].y-dian[j].y));
			}
		}
		SPFA();
		printf("Scenario #%d\nFrog Distance = %.3lf\n\n",++time,dis[2]);
	}
}


以前我们用dis数组保存起点到任何一点的距离,现在我们用dis【x】保存的是起点到这个点x的最小距离过程中,其中最大的一个步数。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值