转自:http://blog.sina.com.cn/s/blog_6635898a0100isir.html
题意:一个池塘中分布着n块可供青蛙跳跃的石头,坐标分别为sto[i].x和sto[i].y,给出Freddy和Fiona站的石头,问Freddy想借助这些石头,跳去Fiona那,它的跳跃距离至少是多少?
思路:dijkstra的变形。由于每条边的权值必为正,故开始时就对连接Freddy点(源点)的所有边进行松弛,得出最小dict[]值的点s,其值便已确定,以后不会再改变(这点很重要,证明)。然后以s为源点,继续这样的操作,直至Freddy这点的dict[]值被确定。最坏情况下,每条边都访问一次,时间复杂度为0(n^2)。
源代码:(368K 0MS)
#include<iostream>
#include<cmath>
using namespace std;
const int Max = 205;
const int inf = 99999999;
struct{
int x, y;
}sto[Max];
int n;
float edge[Max][Max], dict[Max];
bool vis[Max];
void init_data(){
memset(vis, false, sizeof(vis));
vis[0] = true;
for(int i = 1; i < n; i ++)
dict[i] = inf;
}
float find_edge(int u, int v){ // 计算两石头之间的距离,即边长。
float dx = sto[u].x - sto[v].x;
float dy = sto[u].y - sto[v].y;
return sqrt(dx * dx + dy * dy);
}
float max(float a, float b){
return a > b ? a : b;
}
void dijkstra(){ // dij的变形。
int now = 0, count = n - 1;
while(count --){
int k;
float min_dis = inf;
for(int i = 1; i < n; i ++)
if(!vis[i]){
if(dict[i] > max(dict[now], edge[i][now])) // 取路程中最长的值。
dict[i] = max(dict[now], edge[i][now]);
if(min_dis > dict[i]){
min_dis = dict[i];
k = i;
}
}
if(k == 1) return; // 若sto[1]已被访问,则说明已得到sto[0]到sto[1]的最短路径。跳出。
now = k;
vis[k] = true;
}
}
int main(){
int t = 0;
while(cin >> n && n != 0){
init_data();
for(int i = 0; i < n; i ++){
cin >> sto[i].x >> sto[i].y; // 这样Freddy的点默认为sto[0],Fiona的点默认为sto[1]。
for(int j = i - 1; j >= 0; j --){
float val = find_edge(i, j);
edge[i][j] = edge[j][i] = val;
}
}
dijkstra();
printf("Scenario #%d\nFrog Distance = %.3f\n\n", ++t, dict[1]);
}
return 0;
}