B - Frogger POJ - 2253
题意: 从 1 号点出发,找每一条能够到达 2 号点的路径,每条路径的答案是该路径中相邻两点之间距离的最大值,求这些答案中的最小值。
思路: 感觉不是最短路,是不是用二分查找呢,但是又要遍历每一条路径,那就直接套用最短路的思想,从第 1 号点出发,贪心的求出其能够到达的点的最小距离,走到这一点(此时一定是路径上最大距离的最小值),再用这个距离更新没有被访问过的每一个点的路径答案(路径最大跨度为当前点的最大跨度与当前点到各个点的距离中的较大者),直到所有的点都被访问过,则返回最终答案即可。
AC代码
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
using namespace std;
const int inf = 0x3f3f3f3f;
const int maxn = 250;
double dis[maxn]; // 每个点到达 起点 的青蛙跳
bool vis[maxn];
double a[maxn][maxn]; // 两点之间的距离
double x[maxn], y[maxn];
int n;
void init() {
memset(vis, 0, sizeof(vis));
memset(a, inf, sizeof(a));
}
double dijkstra() {
int u;
double minn = inf;
for(int i = 1; i <= n; i++) {
dis[i] = a[1][i];
}
vis[1] = 1;
while(1) {
minn = inf;
for(int i = 1; i <= n; i++) {
if(!vis[i] && dis[i] < minn) { // 每次从当前点出发找一个最小的距离跨度
minn = dis[i];
u = i;
}
}
if(minn == inf) break; // 所有点都更新过了
vis[u] = 1;
// 更新还没有被标记过的点到起点的最小距离跨度(因为标记过的点都已经贪心的选取了最小跨度所以没必要再次更新)
for(int i = 1; i <= n; i++) {
if(!vis[i] && a[u][i] < inf && dis[i] > max(dis[u], a[u][i])) dis[i] = max(dis[u], a[u][i]); // 每次确定一个点之后都要考虑当前是否能跨到下一块石头上
}
}
return dis[2];
}
int main() {
// freopen("test.in", "r", stdin);
int kase = 0;
while(~scanf("%d", &n) && n) {
init();
for(int i = 1; i <= n; i++) scanf("%lf%lf", &x[i], &y[i]);
for(int i = 1; i <= n; i++)
for(int j = 1; j <= n; j++)
a[i][j] = sqrt(pow(x[i]-x[j],2)+pow(y[i]-y[j],2)); // 存每个点之间的距离
double ans = dijkstra();
printf("Scenario #%d\n", ++kase);
printf("Frog Distance = %.3f\n\n", ans); // 注意输出用 %.3f 我用%.3lfWA了好几发
}
return 0;
}