【无标题】Frogger(迪杰斯特拉做)

描述:

 弗雷迪·青蛙坐在湖中央的一块石头上。突然,他注意到坐在另一块石头上的菲奥娜·青蛙。他计划去看望她,但由于水很脏,到处都是游客的防晒霜,他想避免游泳,而是通过跳跃到达她。
不幸的是,菲奥娜的石头超出了他的跳跃范围。因此,弗雷迪考虑使用其他石头作为中间的停留点,并通过几次小跳跃的顺序到达她。
要执行给定的跳跃序列,青蛙的跳跃范围显然必须至少与序列中发生的最长跳跃一样长。
因此,青蛙在两块石头之间的距离(人类也称之为最小最大距离)被定义为两块石头之间所有可能路径上的最小必要跳跃范围。

您将获得弗雷迪的石头,菲奥娜的石头和湖中所有其他石头的坐标。你的工作是计算弗雷迪和菲奥娜的石头之间的青蛙距离。

输入

输入将包含一个或多个测试用例。每个测试用例的第一行将包含结石数 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++;
	}
}

 

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值