# Floyd-Warshall# Graph# Greedy

c125 - 00534 - Frogger

🔗 前往 ZeroJudge 原題

題目描述

題目描述了青蛙 Freddy 想要跳到 Fiona 的石頭上,但直接跳躍距離過遠。因此,Freddy 必須利用湖中的其他石頭作為中繼站。題目要求計算蛙跳距離,即 Freddy 從起始石頭跳到 Fiona 石頭的路徑中,所需的最大跳躍距離的最小值。

解題思路

本題可以建模為一個圖論問題。將每個石頭視為圖中的一個節點,石頭之間的距離作為邊的權重。蛙跳距離實際上就是從起始節點到目標節點的所有路徑中,最大邊權重的最小值。可以使用 Floyd-Warshall 演算法來計算所有節點對之間的最短路徑,並在計算過程中找到滿足條件的最小最大邊權重。

Floyd-Warshall 演算法的核心思想是動態規劃,它通過迭代更新所有節點對之間的距離,最終得到所有節點對之間的最短路徑。在每次迭代中,它考慮是否通過中間節點 k 來縮短從節點 i 到節點 j 的路徑。

具體來說,程式碼首先計算出所有石頭之間的距離,並將其存儲在 fl 陣列中。然後,使用 Floyd-Warshall 演算法更新 fl 陣列,使得 fl[i][j] 儲存從石頭 i 到石頭 j 的蛙跳距離。最後,輸出從石頭 0 到石頭 1 的蛙跳距離。

複雜度分析

  • 時間複雜度: O(n^3),其中 n 是石頭的數量。Floyd-Warshall 演算法的時間複雜度為 O(n^3)。
  • 空間複雜度: O(n^2),其中 n 是石頭的數量。fl 陣列需要 O(n^2) 的空間來儲存所有節點對之間的距離。

程式碼

#include <iostream>
#include <iomanip>
#include <cmath>
using namespace std;
int n,ca;
struct p{
	double x,y;
};
p a[210];
double fl[210][210],ans;
double dis(int xx,int yy){
	double xd=a[xx].x-a[yy].x,yd=a[xx].y-a[yy].y;
	if(xd<0)xd*=-1;
	if(yd<0)yd*=-1;
	return sqrt(xd*xd+yd*yd);
}
int main(){
	cin.tie(0); ios::sync_with_stdio(false);
	while(cin >> n){
		if(n==0)break;
		ans=0;
		for(int i=0;i<210;++i)
			for(int j=0;j<210;++j)
				fl[i][j]=0;
		for(int i=0;i<n;++i)
			cin >> a[i].x >> a[i].y;
		for(int i=0;i<n;++i)
			for(int j=0;j<n;++j){
				if(i==j)fl[i][j]=0;
				else fl[i][j]=dis(i,j);
			}
		for(int k=0;k<n;++k)
			for(int i=0;i<n;++i)
				for(int j=0;j<n;++j){
					double ds=fl[i][k];
					if(ds<fl[k][j])ds=fl[k][j];
					if(fl[i][j]>ds){
						fl[i][j] = ds;
					}
				}
		cout << "Scenario #" << ++ca << "\nFrog Distance = " <<  fixed <<  setprecision(3)  << fl[0][1] << "\n\n"; 
	}
}

Discussion