描述:
弗雷迪·青蛙坐在湖中央的一块石头上。突然,他注意到坐在另一块石头上的菲奥娜·青蛙。他计划去看望她,但由于水很脏,到处都是游客的防晒霜,他想避免游泳,而是通过跳跃到达她。
不幸的是,菲奥娜的石头超出了他的跳跃范围。因此,弗雷迪考虑使用其他石头作为中间的停留点,并通过几次小跳跃的顺序到达她。
要执行给定的跳跃序列,青蛙的跳跃范围显然必须至少与序列中发生的最长跳跃一样长。
因此,青蛙在两块石头之间的距离(人类也称之为最小最大距离)被定义为两块石头之间所有可能路径上的最小必要跳跃范围。
您将获得弗雷迪的石头,菲奥娜的石头和湖中所有其他石头的坐标。你的工作是计算弗雷迪和菲奥娜的石头之间的青蛙距离。
输入
输入将包含一个或多个测试用例。每个测试用例的第一行将包含结石数 n (2<=n<=200)。接下来的 n 行分别包含两个整数 xi,yi (0 <= xi,yi <= 1000),表示石#i的坐标。1号石头是弗雷迪的石头,2号石头是菲奥娜的石头,其他n-2块石头无人居住。每个测试用例后面都有一个空行。对于 n,输入由零 (0) 的值终止。
输出
对于每个测试用例,打印一行“场景#x”和一行“青蛙距离= y”,其中x被替换为测试用例编号(它们从1开始编号),y被替换为适当的实数,打印成三个小数。在每个测试用例之后放置一个空行,甚至在最后一个测试用例之后。
示例输入
2 0 0 3 4 3 17 4 19 4 18 5 0
示例输出
Scenario #1 Frog Distance = 5.000 Scenario #2 Frog Distance = 1.414
解读:这是个最短路变形问题,求得不是最短路,是从一个地方跳到另一个地方,每次跳的最小的最大距离,详情见代码。这里我用的是迪杰斯特拉,有时间还会用别的算法做做。
#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
#define maxn 300
using namespace std;
const int inf = 0x3f3f3f3f;
double g[maxn][maxn];
int n;
int x[maxn], y[maxn];
int vis[maxn];
double dis[maxn];
void Dijkstra(int s)
{
memset(vis, 0, sizeof(vis));
for (int i = 1; i <= n; i++)
dis[i] = inf;//这一步很奇怪,不能用memset。
//调试发现这错了没在意,和网上对照了一下就这里不对,但是不知道为啥不能用。
dis[s] = 0;
for (int i = 1; i <= n - 1; i++)
{
int pos=-1;
for (int j = 1; j <= n; j++)
if (vis[j] == 0 && (pos == -1 || dis[pos] > dis[j]))
pos = j;
vis[pos] = 1;
for (int j = 1; j <= n; j++)
dis[j] = min(dis[j], max(dis[pos], g[pos][j]));//要求的是跳的最小的最大范围(尽量保证跳的最大幅度要小)!!我以为还以为是最短路,错的离谱,卡了好几天居然是因为读题。
}
}
int main()
{
int t=1;
while (scanf("%d", &n)&&n)
{
int x[maxn], y[maxn];
memset(g, inf, sizeof(g));
for (int i = 1; i <= n; i++)
scanf("%d %d", &x[i], &y[i]);//用数组收集坐标,算距离。和模板区别就是距离自己算
int j;
for (int i = 1; i <= n; i++)
for (j = 1; j <= n; j++)
g[j][i] = sqrt((1.0 * x[i] - x[j]) * (x[i] - x[j]) + (y[i] - y[j]) * (y[i] - y[j]));//i到j的距离
Dijkstra(1);
printf("Scenario #%d\n", t);
printf("Frog Distance = %.3f\n\n", dis[2]);
t++;
}
}