Frogger POJ - 2253 (Dijkstra算法重新理解)

题目大意

给定起始点和终点的坐标,然后再给几个中间点的坐标,问怎么走可以使得从起点到终点最长的跳跃路径最短。

思路

刚刚学会这个最短路算法还不是很熟练,但我拿到题很快就wa了,因为我想当然的套了个dj算法模版,并没有思考题意,当我重新读题,发现这并不是一道简单的从起点到终点最短路问题,而是最长跨越距离最短的问题。
这样d[i]就不在表示从起点到i点最短路径了,而是表示从起点到i点的最大跳跃距离。
然后就是dj算法那个思路,写着写着发现这个算法和之前接触的prim算法有点像诶~

这道题与普通最短路的区别和联系

1.区别:普通最短路问题是两个点通过加入其他点更新这两个的最短距离,而这里不一样之处在于更新的不是最短距离而是最长跳跃的最短距离,所以d[i]的含义有所不同。
2.联系:dj的基本思路是完全一样的,都是贪心的思想找到最合题的点,用这个点更新其他点。

代码:

#include <cstdio>
#include <algorithm>
#include <cmath>
#include <cstring>
using namespace std;
const int maxn = 200 + 10;
const int inf = 0x3f3f3f3f;

double d[maxn];     // d[i] 表示从 1 出发 到 i 中的最长跳跃距离最小的大小
int n;
int vis[maxn];
double road[maxn][maxn];

int kase = 0;

struct node {
    int x, y;
} p[maxn];

double get_dis(node a, node b) {
    return sqrt(pow((double)(a.x-b.x), 2) + pow((double)(a.y-b.y), 2));
}

void dj() {
    int v;
    memset(vis, 0, sizeof(vis));
    for(int i = 1; i <= n; i++) {         // 初始化
        d[i] = road[1][i];
    }
    vis[1] = 1;
    for(int i = 2; i <= n; i++) {         // 因为已经放进点1了所以这里这要再放n-1个点就行了
        double mindis = inf;
        for(int j = 1; j <= n; j++) {
            if (!vis[j] && d[j] < mindis) {  
                mindis = d[j];
                v = j;
            }
        }
        vis[v] = 1;
        for (int j = 1; j <= n; j++) {
            if (!vis[j]) {
                d[j] = min(d[j], max(d[v], road[v][j]));        // 更新
            }
        }
    }
    printf("Scenario #%d\n", ++kase);
    printf("Frog Distance = %.3lf\n\n", d[2]);
}

int main() {
    //freopen("input.txt", "r", stdin);
    while(~scanf("%d", &n) & n) {
        for(int i = 1; i <= n; i++) {
            scanf("%d%d", &p[i].x, &p[i].y);
        }
        for(int i = 1; i <= n; i++) {
            for(int j = i; j <= n; j++) {
                road[i][j] = road[j][i] = get_dis(p[i], p[j]);
            }
        }
        dj();
    }
    return 0;
}
  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值