【Dijkstra变形】-- 通路中最小边

题目来源: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;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值