POJ - 2253 Dijkstra最短路

题目

湖中有n块石头,编号从1到n,有两只青蛙,Bob在1号石头上,Alice在2号石头上,Bob想去看望Alice,但由于水很脏,他想避免游泳,于是跳着去找她。但是Alice的石头超出了他的跳跃范围。因此,Bob使用其他石头作为中间站,通过一系列的小跳跃到达她。两块石头之间的青蛙距离被定义为两块石头之间所有可能路径上的最小必要跳跃距离,某条路径的必要跳跃距离即这条路径中单次跳跃的最远跳跃距离。你的工作是计算Alice和Bob石头之间的青蛙距离。

输入

多实例输入
先输入一个整数n表示石头数量,当n等于0时结束。
接下来n行依次给出编号为1到n的石头的坐标xi , yi。
2 <= n <= 200
0 <= xi , yi <= 1000

输出

先输出"Scenario #x", x代表样例序号。
接下来一行输出"Frog Distance = y", y代表你得到的答案。
每个样例后输出一个空行。
(ps:wa有可能是精度问题,g++不对可以用c++尝试,都不对就是代码问题)

样例

输入样例1

2
0 0
3 4

3
17 4
19 4
18 5

0

输出样例1

Scenario #1
Frog Distance = 5.000

Scenario #2
Frog Distance = 1.414

分析

因为是单源起点,所以用dijkstra和Floyd都行,不同之处在于不记录到每个点的最短距离,记录到每个点的过程中最长边的长度

AC代码

#include <iostream>
#include <cstdio>
#include <fstream>
#include <algorithm>
#include <cmath>
#include <deque>
#include <vector>
#include <queue>
#include <string>
#include <cstring>
#include <map>
#include <stack>
#include <set>
#include <sstream>
#define mod 1000000007
#define eps 1e-6
#define ll long long
#define INF 0x3f3f3f3f
#define debug_ cout<<"====>"<<endl;
#define ME0(x) memset(x,0,sizeof(x))
#define de_bug_arr(ffkinp,fkfn) 	for(int fkeei=0;fkeei<fkfn;fkeei++)cout<<ffkinp[fkeei]<<' ';
using namespace std;
struct p{
	double x,y;
};
double qlen(struct p a,struct p b){
	return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));
}
double d[300];//d[]数组表示的 含义:从第一个点(inp【0】)到该点路径中最大跳跃距离的最小值 
bool jg[300];//用于记录该点是否被当做过查找过程中的中间节点!!不是是否被访问过,查找过程中每个邻接点都被访问过 
int main(){
	int n;//石子数量计数器 
	int cj=1;//当前样例计数器 
	while(scanf("%d",&n)!=EOF){
		if(n==0)break;//特判,当为0是跳出循环 
		struct p inp[210];//定义输入数组用于储存石子的横纵坐标 
		//=================================================输入		
		for(int i=0;i<n;i++)
		{//依次输入各个点的坐标 
			scanf("%lf %lf",&inp[i].x,&inp[i].y);
		}
		//=================================================特判 
		if(n==2){//如果n为2,则只有两个石头(起点和终点),此时 直接输出两点间的距离就是最小值 
		printf("Scenario #%d\n",cj++);
	    printf("Frog Distance = %.3f\n\n",qlen(inp[0],inp[1]));
	    continue; 
		}
		//=================================================初始化 
		memset(jg,0,sizeof(jg));//将每个点标记为未被访问的状态
//  																if(!jg[1]) debug_; 
		for(int i=1;i<n;i++){
			d[i]=qlen(inp[i],inp[0]);//初始化每个点到起点的最小最大值为该点到起点的直线距离(这个值一定>=最小值) 
//			cout<<"inp "<<i<<"=="<<d[i]<<endl;
		}
//		cout<<"==="<<d[n-2]<<"==="<<d[n-1]<<endl;
        //=================================================dijkstra变形部分 
        jg[0]=true;//从起点开始查找,则把起点置为已访问状态(true) 
	    for(int i=1;i<n;i++){
	    	int mid=-1;
			for(int j=1;j<n;j++){
				if((d[j]<d[mid]||mid==-1)&&!jg[j]){
					mid=j;
				}
			}
		//	cout<<"J"<<mid<<endl;
			jg[mid]=true;
			//cout<<"="<<mid<<endl;
			for(int j=1;j<n;j++){
				if(!jg[j]){
					d[j]=min(d[j],max(d[mid],qlen(inp[j],inp[mid])));
			//		cout<<"len"<<qlen(inp[j],inp[mid])<<endl;
				}
			}
		}
		//=================================================输出结果部分 
	  printf("Scenario #%d\n",cj++);
	  printf("Frog Distance = %.3f\n\n",d[1]);
	}
	return 0;
}

反思

逆大天,最开始求的是最短路中的最长边,然而题目的要求是要找这个过程中最少需要跳多远...也就是说总路程无所谓,只要过程中跳的最远的那一条是最短的就行

#include <iostream>
#include <cstdio>
#include <fstream>
#include <algorithm>
#include <cmath>
#include <deque>
#include <vector>
#include <queue>
#include <string>
#include <cstring>
#include <map>
#include <stack>
#include <set>
#include <sstream>
#define mod 1000000007
#define eps 1e-6
#define ll long long
#define INF 0x3f3f3f3f
#define debug_ cout<<"====>"<<endl;
#define ME0(x) memset(x,0,sizeof(x))
#define de_bug_arr(ffkinp,fkfn) 	for(int fkeei=0;fkeei<fkfn;fkeei++)cout<<ffkinp[fkeei]<<' ';
using namespace std;
struct p{
	double x,y;
};
double qlen(struct p a,struct p b){
	return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));
}
double d[300];//d[]数组表示的 含义:从第一个点(inp【0】)到该点路径中最大跳跃距离的最小值 
bool jg[300];//用于记录该点是否被当做过查找过程中的中间节点!!不是是否被访问过,查找过程中每个邻接点都被访问过 
int main(){
	int n;//石子数量计数器 
	int cj=1;//当前样例计数器 
	while(scanf("%d",&n)!=EOF){
		if(n==0)break;//特判,当为0是跳出循环 
		struct p inp[210];//定义输入数组用于储存石子的横纵坐标 
		//=================================================输入		
		for(int i=0;i<n;i++)
		{//依次输入各个点的坐标 
			scanf("%lf %lf",&inp[i].x,&inp[i].y);
		}
		//=================================================特判 
		if(n==2){//如果n为2,则只有两个石头(起点和终点),此时 直接输出两点间的距离就是最小值 
		printf("Scenario #%d\n",cj++);
	    printf("Frog Distance = %.3f\n\n",qlen(inp[0],inp[1]));
	    continue; 
		}
		//=================================================初始化 
		memset(jg,0,sizeof(jg));//将每个点标记为未被访问的状态
//  																if(!jg[1]) debug_; 
		for(int i=1;i<n;i++){
			d[i]=qlen(inp[i],inp[0]);//初始化每个点到起点的最小最大值为该点到起点的直线距离(这个值一定>=最小值) 
//			cout<<"inp "<<i<<"=="<<d[i]<<endl;
		}
//		cout<<"==="<<d[n-2]<<"==="<<d[n-1]<<endl;
        //=================================================dijkstra变形部分 
        jg[0]=true;//从起点开始查找,则把起点置为已访问状态(true) 
	    for(int i=1;i<n;i++){
	    	int mid;
	    	double min_=300000; 
			for(int j=1;j<n;j++){
				if(min_>qlen(inp[i],inp[j])&&!jg[j]){
					min_=qlen(inp[i],inp[j]);
					mid=j;
				}
			}
		//	cout<<"J"<<mid<<endl;
			jg[mid]=true;
			//cout<<"="<<mid<<endl;
			for(int j=1;j<n;j++){
				if(!jg[j]){
					d[j]=min(d[j],max(d[mid],qlen(inp[j],inp[mid])));
			//		cout<<"len"<<qlen(inp[j],inp[mid])<<endl;
				}
			}
		}
		//=================================================输出结果部分 
	  printf("Scenario #%d\n",cj++);
	  printf("Frog Distance = %.3f\n\n",d[1]);
	}
	return 0;
}
posted @ 2022-11-02 17:21  ~Chitoge  阅读(30)  评论(0)    收藏  举报