Frogger
Time Limit: 1000MS Memory Limit: 65536K
Total Submissions: 66037 Accepted: 20429
Description
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
问题描述
有两只青蛙,一个要从石头1跳到石头2去拜访另一支青蛙,不能游泳。给出石头的个数和坐标,要求青蛙从石头1跳到石头2(可以借助其它石头)所需要的最小跳跃范围。
问题分析
把坐标转化为路径长度记录。然后利用最短路处理。最短路的3种方法都可以解决。
与原来的最短路不同的是,不是路长更新,而是跳跃的范围更新。
如:从a点跳到b点再跳到c点与直接从a点跳到c点相比,如果Rac>max(Rab,Rbc),那么就更新Rac=max(Rab,Rbc),表示的是从a到c可以以max(Rab,Rbc)的跳跃范围到达,也就是从a到b再到c。
这与最短路的Lac>(Lab+Lbc)就更新Lac=Lab+Lbc是一样的思路。
c++程序如下
Floyd算法
#include<iostream>
#include<cstdio>
#include<cmath>
using namespace std;
const int N = 205;
double min(double x, double y){ return x < y ? x : y; }
double max(double x, double y){ return x > y ? x : y; }
int n, x[N], y[N], time = 0;
double dirt[N][N];
void floyd();
int main()
{
while (scanf_s("%d", &n) != EOF&&n)
{
time++;
for (int i = 1; i <= n; i++)
cin >> x[i] >> y[i];
floyd();
printf("Scenario #%d\nFrog Distance = %.3llf\n\n", time, dirt[1][2]);
}
return 0;
}
void floyd()
{
int i, j, k;
for (i = 1; i <= n; i++)
for (j = i + 1; j <= n; j++)
dirt[i][j] = dirt[j][i] = sqrt(double(x[i] - x[j])*(x[i] - x[j]) + double(y[i] - y[j])*(y[i] - y[j]));
for (k = 1; k <= n; k++)
for (i = 1; i <= n; i++)
for (j = 1; j <= n; j++)
dirt[i][j] = min(dirt[i][j], max(dirt[i][k], dirt[k][j]));
}
Dijkstra算法
#include<iostream>
#include<cmath>
#include<cstdio>
using namespace std;
const int N = 205;//石头最大数量
int n;//石头个数
double map[N][N];//地图
double dist[N];//起点到其它点的距离
bool vis[N];//访问标记
void dijkstra();
double min(double x, double y) { return x < y ? x : y; }
double max(double x, double y) { return x>y ? x : y; }
int main()
{
int x[N], y[N], time = 1;
while (scanf_s("%d", &n) != EOF&&n)
{
for (int i = 1; i <= n; i++)//输入坐标
{
scanf_s("%d %d", x + i, y + i);
}
for (int i = 1; i < n; i++)//坐标转换为距离
{
for (int j = i + 1; j <= n; j++)
{
map[i][j] = map[j][i] = sqrt(pow(double(x[i] - x[j]), 2.0) + pow(double(y[i] - y[j]), 2.0));
}
}
dijkstra();
printf("Scenario #%d\nFrog Distance = %.3lf\n\n", time++, dist[2]);
}
return 0;
}
void dijkstra()
{
int i, j, temp;
double ans;
vis[1] = 1;
dist[1] = 0;
for (i = 2; i <= n; i++)//初始化
{
vis[i] = 0;
dist[i] = map[1][i];
}
for (i = 1; i < n; i++)//循环次数
{
ans = 0x3f3f3f3f;
for (j = 2; j <= n; j++)//找出最短边(范围)
{
if (!vis[j] && dist[j] < ans)
{
ans = dist[j];
temp = j;
}
}
if (ans == 0x3f3f3f3f) break;//说明已经无合适的边
vis[temp] = 1;
for (j = 2; j <= n; j++)//更新
dist[j] = min(dist[j], max(dist[temp], map[temp][j]));//松弛操作
}
}
Spfa算法
#include<iostream>
#include<cmath>
#include<queue>
#include<cstdio>
using namespace std;
const int N = 205;
const int inf = 0x3f3f3f3f;
int n;
bool vis[N];
double map[N][N];
double dist[N];
void spfa();
double max(double x, double y){ return x>y ? x : y; }
int main()
{
int x[N], y[N], i, j, time = 1;
while (scanf_s("%d", &n) != EOF&&n)
{
for (i = 1; i <= n; i++)
{
scanf_s("%d %d", x + i, y + i);
}
for (i = 1; i < n; i++)
{
for (j = i + 1; j <= n; j++)
{
map[i][j] = map[j][i] = sqrt(pow(double(x[i] - x[j]), 2.0) + pow(double(y[i] - y[j]), 2.0));//把坐标转换为距离
}
}
spfa();
printf("Scenario #%d\nFrog Distance = %.3lf\n\n", time++, dist[2]);
}
return 0;
}
void spfa()
{
int i;
queue<int>Q;
for (i = 1; i <= n; i++)//初始化
{
vis[i] = 0;
dist[i] = (double)inf;
}
vis[1] = 1;
dist[1] = 0;
Q.push(1);
while (!Q.empty())
{
int now=Q.front();
Q.pop();
vis[now] = 0;
for (i = 1; i <= n; i++)
{
if (dist[i] > max(dist[now], map[now][i]))//松弛操作
{
dist[i] = max(dist[now], map[now][i]);
if (!vis[i])
{
Q.push(i);
vis[i] = 1;
}
}
}
}
}

博客围绕青蛙从一块石头跳到另一块石头所需最小跳跃范围问题展开。给出石头个数和坐标,需计算最小跳跃范围。可将坐标转化为路径长度,用Floyd、Dijkstra、Spfa三种最短路算法解决,不同的是更新的是跳跃范围而非路长。

2万+

被折叠的 条评论
为什么被折叠?



