給定 n ≤ 200 個石頭座標,石頭 1 為起點,石頭 2 為終點。青蛙可跳躍任意兩石頭間,跳躍距離為歐氏距離。
定義路徑的代價為路徑上最長單次跳躍距離。
求從 1 到 2 所有路徑中,代價最小者(即 Minimax 路徑 / Frog Distance)。
經典 Floyd 求最短路:d[i][j] = min(d[i][j], d[i][k] + d[k][j])
Minimax 版本:d[i][j] = min(d[i][j], max(d[i][k], d[k][j]))
含義:經過 k 的路徑最長邊為兩段最長邊的最大值;取所有中繼點 k 的最小值。
#include
#include
#include
#include
using namespace std;
const int MAXN = 205;
const double INF = 1e100;
double dist[MAXN][MAXN];
int x[MAXN], y[MAXN];
int main() {
int n, cas = 0;
while (scanf("%d", &n) == 1 && n) {
for (int i = 1; i <= n; ++i) {
scanf("%d%d", &x[i], &y[i]);
for (int j = 1; j < i; ++j) {
int dx = x[i] - x[j], dy = y[i] - y[j];
dist[i][j] = dist[j][i] = sqrt(dx*dx + dy*dy);
}
dist[i][i] = 0;
}
// Floyd-Warshall Minimax
for (int k = 1; k <= n; ++k)
for (int i = 1; i <= n; ++i)
for (int j = 1; j <= n; ++j)
dist[i][j] = min(dist[i][j], max(dist[i][k], dist[k][j]));
printf("Scenario #%d\nFrog Distance = %.3f\n\n", ++cas, dist[1][2]);
}
return 0;
}
將邊權視為「代價」,使用優先隊列,狀態為 (maxEdgeSoFar, node),每次取出最小 maxEdgeSoFar 的節點擴展。
複雜度 O(E log V) = O(V² log V),對稠密圖 (V=200) 略慢於 Floyd O(V³) 但同數量級。
Input:
2
0 0
3 4
3
17 4
19 4
18 5
0
Output:
Scenario #1
Frog Distance = 5.000
Scenario #2
Frog Distance = 1.414