弗雷迪青蛙坐在湖中央的一块石头上。突然他注意到坐在另一块石头上的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的最小距离过程中,其中最大的一个步数。