Frogger POJ - 2253 最短路Floyd,Dijkstra,SPFA

Freddy Frog is sitting on a stone in the middle of a lake. Suddenly he notices Fiona Frog who is sitting on another stone. He plans to visit her, but since the water is dirty and full of tourists' sunscreen, he wants to avoid swimming and instead reach her by jumping. 
Unfortunately Fiona's stone is out of his jump range. Therefore Freddy considers to use other stones as intermediate stops and reach her by a sequence of several small jumps. 
To execute a given sequence of jumps, a frog's jump range obviously must be at least as long as the longest jump occuring in the sequence. 
The frog distance (humans also call it minimax distance) between two stones therefore is defined as the minimum necessary jump range over all possible paths between the two stones. 

You are given the coordinates of Freddy's stone, Fiona's stone and all other stones in the lake. Your job is to compute the frog distance between Freddy's and Fiona's stone. 

Input

The input will contain one or more test cases. The first line of each test case will contain the number of stones n (2<=n<=200). The next n lines each contain two integers xi,yi (0 <= xi,yi <= 1000) representing the coordinates of stone #i. Stone #1 is Freddy's stone, stone #2 is Fiona's stone, the other n-2 stones are unoccupied. There's a blank line following each test case. Input is terminated by a value of zero (0) for n.

Output

For each test case, print a line saying "Scenario #x" and a line saying "Frog Distance = y" where x is replaced by the test case number (they are numbered from 1) and y is replaced by the appropriate real number, printed to three decimals. Put a blank line after each test case, even after the last one.

Sample Input

2
0 0
3 4

3
17 4
19 4
18 5

0

Sample Output

Scenario #1
Frog Distance = 5.000

Scenario #2
Frog Distance = 1.414

题意:

有两只青蛙和若干块石头,现在已知这些东西的坐标,两只青蛙A坐标和青蛙B坐标是第一个和第二个坐标,现在A青蛙想要到B青蛙那里去,并且A青蛙可以借助任意石头的跳跃,而从A到B有若干通路,问从A到B的所有通路上的最大边,比如有  有两条通路  1(4)5 (3)2 代表1到5之间的边为4,  5到2之间的边为3,那么该条通路跳跃范围(两块石头之间的最大距离)为 4,  另一条通路 1(6) 4(1) 2 ,该条通路的跳跃范围为6, 两条通路的跳跃范围分别是 4 ,6,我们要求的就是最小的那一个跳跃范围,即4,

思路:最短路算法,由于数据较小,因此可以用Floyd算法,Dijkstra算法,SPFA算法。但这一题最简单的还是用Floyd算法。

Floyd算法:

 1 #include <cstdio>
 2 #include <fstream>
 3 #include <algorithm>
 4 #include <cmath>
 5 #include <deque>
 6 #include <vector>
 7 #include <queue>
 8 #include <string>
 9 #include <cstring>
10 #include <map>
11 #include <stack>
12 #include <set>
13 #include <sstream>
14 #include <iostream>
15 #define mod 998244353
16 #define eps 1e-6
17 #define ll long long
18 #define INF 0x3f3f3f3f
19 using namespace std;
20 
21 //ma用来存放两个石头之间的距离
22 double ma[210][210];
23 int main()
24 {
25     //x,y数组存放地点
26     double x[210],y[210];
27     int n,ans=1;
28     //n为0时退出
29     while(scanf("%d",&n)&&n)
30     {
31         int a,b;
32         for(int i=1;i<=n;i++)
33         {
34             scanf("%lf %lf",&x[i],&y[i]);
35         }
36         //初始化ma数组为0,是为了保证求的是最大距离中的小距离
37         memset(ma,0,sizeof(ma));
38         for(int i=i=1;i<=n;i++)
39         {
40             for(int j=1;j<=n;j++)
41             {
42                 //录入两个石头之间的距离
43                 ma[i][j]=ma[j][i]=sqrt(pow(x[i]-x[j],2.0)+pow(y[i]-y[j],2.0));
44             }
45         }
46         //Floyd算法核心
47         for(int k=1;k<=n;k++)
48         {
49             for(int i=1;i<=n;i++)
50             {
51                 for(int j=1;j<=n;j++)
52                 {
53                     //许多通路中最大距离中的最小距离
54                     ma[i][j]=min(ma[i][j],max(ma[i][k],ma[k][j]));
55                 }
56             }
57         }
58         printf("Scenario #%d\nFrog Distance = %.3lf\n\n",ans++,ma[1][2]);
59     }
60 
61 }

Dijkstra算法

 1 #include <cstdio>
 2 #include <fstream>
 3 #include <algorithm>
 4 #include <cmath>
 5 #include <deque>
 6 #include <vector>
 7 #include <queue>
 8 #include <string>
 9 #include <cstring>
10 #include <map>
11 #include <stack>
12 #include <set>
13 #include <sstream>
14 #include <iostream>
15 #define mod 998244353
16 #define eps 1e-6
17 #define ll long long
18 #define INF 0x3f3f3f3f
19 using namespace std;
20 
21 //dis用来存放到1之间的距离
22 double dis[310];
23 //ma用来存放两个石头之间的距离
24 double ma[210][210];
25 void dijkstra(int m)
26 {
27     int i;
28     //vis数组标记已经找过的最短路
29     bool vis[1010];
30     memset(vis,0,sizeof(vis));
31     for(int i=1;i<=m;i++)
32     {
33         dis[i]=INF;
34     }
35     dis[1]=0;
36     for(int i=1;i<=m;i++)
37     {
38         //mi记录当前到1距离最小的值
39         double mi=INF;
40         //k表示到1距离最小的点
41         int k=1;
42         for(int j=1;j<=m;j++)
43         {
44             //当未标记这个点,并且这个点到1的距离时最小的时侯成立,
45             if(!vis[j]&&mi>dis[j])
46             {
47                 mi=dis[j];
48                 k=j;
49             }
50         }
51         //已找到1到k点的最小值,所以标记这个点
52         vis[k]=1;
53         for(int j=1;j<=m;j++)
54         {
55             //所有通路中最大距离中的最小数
56             dis[j]=min(dis[j],max(dis[k],ma[k][j]));
57         }
58     }
59 }
60 
61 int main()
62 {
63     //x,y数组存放地点
64     double x[210],y[210];
65     int n,ans=1;
66     //n为0时退出
67     while(scanf("%d",&n)&&n)
68     {
69         int a,b;
70         for(int i=1;i<=n;i++)
71         {
72             scanf("%lf %lf",&x[i],&y[i]);
73         }
74         //初始化ma数组为0,是为了保证求的是最大距离中的小距离
75         memset(ma,0,sizeof(ma));
76         for(int i=i=1;i<=n;i++)
77         {
78             for(int j=1;j<=n;j++)
79             {
80                 //录入两个石头之间的距离
81                 ma[i][j]=ma[j][i]=sqrt(pow(x[i]-x[j],2.0)+pow(y[i]-y[j],2.0));
82             }
83         }
84         dijkstra(n);
85         printf("Scenario #%d\nFrog Distance = %.3lf\n\n",ans++,dis[2]);
86     }
87 
88 }

SPFA算法

 1 #include <cstdio>
 2 #include <fstream>
 3 #include <algorithm>
 4 #include <cmath>
 5 #include <deque>
 6 #include <vector>
 7 #include <queue>
 8 #include <string>
 9 #include <cstring>
10 #include <map>
11 #include <stack>
12 #include <set>
13 #include <sstream>
14 #include <iostream>
15 #define mod 998244353
16 #define eps 1e-6
17 #define ll long long
18 #define INF 0x3f3f3f3f
19 using namespace std;
20 
21 //ma用来存放两个石头之间的距离
22 double ma[210][210];
23 //dis用来存放到1之间的距离
24 double dis[310];
25 //vis数组标记已经找过的最短路
26 bool vis[1010];
27 
28 void spfa(int m)
29 {
30     //qu用来存放需要遍历的石头
31     queue<int> qu;
32     //初始dis为最大数
33     for(int i=1;i<=m;i++)
34     {
35         dis[i]=INF;
36     }
37     //初始vis为0,表示所有点都未被记录
38     memset(vis,0,sizeof(vis));
39     //1不需要记录
40     vis[1]=1;
41     //1到1的距离为0
42     dis[1]=0;
43     //第一个点为1,入队
44     qu.push(1);
45     //当队伍为空时退出
46     while(!qu.empty())
47     {
48         int k=qu.front();
49         qu.pop();
50         //k的记录被推反,重新记录
51         vis[k]=0;
52         //遍历1到m
53         for(int i=1;i<=m;i++)
54         {
55             //如果1到k之间距离加上k到i将距离比1到i点距离小则更新dis
56             if(max(dis[k],ma[k][i])<dis[i])
57             {
58                 //更新dis[i]
59                 dis[i]=max(dis[k],ma[k][i]);
60                 //如果i点已被标记则不入队
61                 if(!vis[i])
62                 {
63                     //由于i点距离被更新,因此需要重新遍历与i连接的点,所以将i点入队,且标记i点
64                     qu.push(i);
65                     vis[i]=1;
66                 }
67             }
68         }
69     }
70 }
71 int main()
72 {
73     //x,y数组存放地点
74     double x[210],y[210];
75     int n,ans=1;
76     //n为0时退出
77     while(scanf("%d",&n)&&n)
78     {
79         int a,b;
80         for(int i=1;i<=n;i++)
81         {
82             scanf("%lf %lf",&x[i],&y[i]);
83         }
84         //初始化ma数组为0,是为了保证求的是最大距离中的小距离
85         memset(ma,0,sizeof(ma));
86         for(int i=i=1;i<=n;i++)
87         {
88             for(int j=1;j<=n;j++)
89             {
90                 //录入两个石头之间的距离
91                 ma[i][j]=ma[j][i]=sqrt(pow(x[i]-x[j],2.0)+pow(y[i]-y[j],2.0));
92             }
93         }
94         spfa(n);
95         printf("Scenario #%d\nFrog Distance = %.3lf\n\n",ans++,dis[2]);
96     }
97 }

 

转载于:https://www.cnblogs.com/mzchuan/p/11469400.html

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值