题目来源:poj 2253 Frogger
题目描述:
题目描述了两只青蛙,第一只青蛙向努力跳到第二只青蛙那里去,位置是按坐标给的。中间可能有一些介质石头,我们要计算的是,为使青蛙跳到目的地,其所需要的跳跃距离的最小值。
与这题通路中最大边十分相似
思路:
松弛条件:选取X集合外条约距离最小的点加入X集合,假设现在选取点u加入X集合,更新点v时—— d [ v ] = m i n ( d [ v ] , m a x ( d [ u ] , g [ u ] [ v ] ) ) d[v]=min(d[v],max(d[u],g[u][v])) d[v]=min(d[v],max(d[u],g[u][v]))。 意思是首先比较到点u的跳跃距离和g[u][v],选择大的一个作为从u到v的需要的跳跃距离,然后再与原来的d[v]比较,选取小的作为新的d[v]。
选取小的d[u] = 3。那更新B点的时候,能否以A作为中介点使s到B的跳跃距离变小呢? m a x ( d [ u ] , g [ u ] [ v ] ) = m a x ( 3 , 5 ) = 5 max(d[u],g[u][v]) = max(3,5) = 5 max(d[u],g[u][v])=max(3,5)=5。比 d [ v ] = 4 d[v]=4 d[v]=4还要大,那么直接从s跳到B吧,不要经过A了。
#include <iostream>
#include <vector>
#include <cmath>
using namespace std;
const int maxn = 1010;
const int INF = 0x3ffffff;
double G[maxn][maxn];
int pos[maxn][2];
bool vis[maxn] = {false};
double dis[maxn]; //从1点到该位置的最大承载量
int N;
double Dijkstra()
{
fill(vis, vis + maxn, false);
fill(dis, dis + maxn, INF * 1.0);
dis[1] = 0; //初始化注意!
for (int i = 1; i <= N; i++) //循环n次
{
int u = -1; //使d[u]最小且还没有被访问的结点
double min = INF * 1.0;
for (int j = 1; j <= N; j++)
{
if (vis[j] == false && dis[j] < min)
{
u = j;
min = dis[j];
}
}
if (u == -1)
{
break;
}
vis[u] = true;
for (int i = 1; i <= N; i++)
{
if (vis[i] == false && G[u][i] != INF && dis[i] > max(dis[u], G[u][i])) //改变松弛条件
{
dis[i] = max(dis[u], G[u][i]);
}
}
}
return dis[2];
}
double cal(int x1, int y1, int x2, int y2)
{
double dist = sqrt(1.0*(x1 - x2) * (x1 - x2) + 1.0*(y1 - y2) * (y1 - y2));
return dist;
}
int main()
{
int index = 1;
while (cin >> N && N != 0)
{
fill(G[0], G[0] + maxn * maxn, INF);
for (int i = 1; i <= N; i++)
{
cin >> pos[i][0] >> pos[i][1];
}
for (int i = 1; i <= N - 1; i++)
{
for (int j = i + 1; j <= N; j++)
{
G[i][j] = G[j][i] = cal(pos[i][0], pos[i][1], pos[j][0], pos[j][1]);
}
}
cout << "Scenario #" << index++ << endl;
double res = Dijkstra();
printf("Frog Distance = %.3lf\n\n", res);
}
return 0;
}