POJ-2253 AND POJ-1797 最短路(dijkstra的两种变形)

题目链接

POJ-2253

POJ1797

最短路学习

如果你还不太清楚相关的最短里的集中算法,可以参考以下博客:
最短路学习

POJ2253

题目思路

复制一下别人的题意,有两只青蛙和若干块石头,现在已知这些东西的坐标,两只青蛙A坐标和青蛙B坐标是第一个和第二个坐标,现在A青蛙想要到B青蛙那里去,并且A青蛙可以借助任意石头的跳跃,而从A到B有若干通路,问从A到B的所有通路上的最大边,比如有 有两条通路 1(4)5 (3)2 代表1到5之间的边为4, 5到2之间的边为3,那么该条通路跳跃范围(两块石头之间的最大距离)为 4, 另一条通路 1(6) 4(1) 2 ,该条通路的跳跃范围为6, 两条通路的跳跃范围分别是 4 ,6,我们要求的就是最小的那一个跳跃范围,即4,用三种方法都能解决,就是说可能存在多条从结点1到结点2的通路,求解的是所有通路中权值最小的,同时在每一条通路中取边值最大的就是青蛙在该条通路上的跳跃范围。

代码

因为本次的数据范围是200所以可以用floyd (O(n^3)) 算法来解

floyd

#include <algorithm>
#include <iostream>
#include <vector>
#include <cstdio>
#include <cstring>
#include <string>
#include <climits>
#include <set>
#include <queue>
#include <cmath>
typedef long long ll;
typedef unsigned long long ull;
using namespace std;

const int maxx = 205;
int x[maxx], y[maxx];
double vis[maxx][maxx];
int n;

void floyd() {
	for (int k = 1; k <= n; ++k)
		for (int i = 1; i <= n; ++i)
			for (int j = 1; j <= n; ++j) {
				vis[i][j] = min(vis[i][j], max(vis[i][k], vis[k][j]));
			}
}

int main() {
	int count = 0;
	while (~scanf("%d", &n) && n) {
		for (int i = 1; i <= n; ++i)
			scanf("%d%d", &x[i], &y[i]);
		memset(vis, 0, sizeof vis);
		for (int i = 1; i <= n; ++i)
			for (int j = i + 1; j <= n; ++j)
					vis[i][j] = vis[j][i] = sqrt(pow(x[i] - x[j], 2) + pow(y[i] - y[j], 2));
		floyd();
		printf("Scenario #%d\nFrog Distance = %.3f\n\n", ++count, vis[1][2]);
	}
		return 0;
}

dijkstra

#include <cstdio>
#include <cmath>
#include <cstring>
#include <algorithm>
using namespace std;
typedef long long ll;
const int maxx = 205;
bool found[maxx];
double dis[maxx];
int x[maxx], y[maxx];
double edge[maxx][maxx];
int n;
const int inf = 0x3f3f3f3f;

void dijkstra() {
    for (int i = 1; i <= n; ++i) 
        dis[i] = edge[1][i];
    memset(found, false, sizeof found);

    for (int i = 1; i <= n; ++i) {
        int minv = -1; double mind = inf;
        for (int j = 1; j <= n; ++j) {
            if (found[j]) continue;
            if (dis[j] < mind) {
                minv = j;
                mind = dis[j];
            }
        }
		if (minv == -1) 
			break;
        for (int j = 1; j <= n; ++j) {
            dis[j] = min(dis[j], max(mind, edge[minv][j]));  //dijsktra变形
        }
        found[minv] = true;
    }
}

int main() {
    int count = 0;
    while (~scanf("%d", &n) && n) {
        for (int i = 1; i <= n; ++i) {
            scanf("%d%d", &x[i], &y[i]);
        }

        for (int i = 1; i <= n; ++i) 
            for (int j = 1; j <= n; ++j)
                edge[i][j] = inf;

        for (int i = 1; i <= n; ++i) 
            for (int j = i; j <= n; ++j) {
                edge[i][j] = edge[j][i] = sqrt(pow(x[i] - x[j], 2) + pow(y[i] - y[j], 2));
            }
        dijkstra();
        printf("Scenario #%d\nFrog Distance = %.3f\n\n", ++count, dis[2]);
    }
    return 0;
}

POJ1797

题目思路

代码

#include <cstdio>
    #include <cmath>
    #include <cstring>
    #include <algorithm>
    using namespace std;
    typedef long long ll;
    const int maxx = 1005;
    bool found[maxx];
    int dis[maxx];
    int edge[maxx][maxx];
    int n;
    const int inf = 0x3f3f3f3f;

    void dijkstra() {
        for (int i = 1; i <= n; ++i) 
            dis[i] = edge[1][i];
        memset(found, false, sizeof found);

        for (int i = 1; i <= n; ++i) {
            int minv = -1, mind = 0;
            for (int j = 1; j <= n; ++j) {
                if (found[j]) continue;     
                if (dis[j] > mind) {
                    minv = j;
                    mind = dis[j];
                }
            }
			if (minv == -1)
				break;
            for (int j = 1; j <= n; ++j) {
                
                dis[j] = max(dis[j], min(mind, edge[minv][j]));
            }
            found[minv] = true;
        }
    }

    int main() {
        int count;
        while (~scanf("%d", &count)) {
            for (int sample = 1; sample <= count; ++sample) {
                int m;
                scanf("%d%d", &n, &m);
                memset(edge, 0, sizeof edge); //初始化为0表示两个点之间能运送0weight的货物,相当于不可走

                int x, y, w;
                for (int i = 1; i <= m; ++i) {
                    scanf("%d%d%d", &x, &y, &w);
                    edge[x][y] = edge[y][x] = w;
                }
                
                dijkstra();
                printf("Scenario #%d:\n%d\n\n", sample, dis[n]);
            }
        }
        return 0;
    }
  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值