POJ2253 Frogger 最短路

该题就是求一只青蛙从1号石头跳到2号石头的所有路径中跳跃距离最大值的最小值。仔细想想的话,将原来dijkstra的dis数组赋值为这个minmax含义,同样满足贪心规则,所以就是普通的dijkstra。

代码如下:

#include <cstring>
#include <cstdio>
#include <cstdlib>
#include <algorithm>
#include <cmath>
#define MAXN 205
using namespace std;

int N;

struct Node
{
    int x, y;
}e[MAXN];

double G[MAXN][MAXN], dis[MAXN]; // 定义dis数组用来保留minmax值,且该值满足贪心规则
int hash[MAXN];

inline double dist(int x, int y)
{
    return sqrt(double((e[x].x-e[y].x)*(e[x].x-e[y].x)+(e[x].y-e[y].y)*(e[x].y-e[y].y)));
} 

double dijkstra()
{ 
    int pos;
    double Min;
    fill(dis, dis+MAXN, 9999999999.);
    memset(hash, 0, sizeof (hash));
    dis[1] = 0; // 到达第一号石头所需要的mm值为0
    hash[1] = 1;
    for (int i = 1; i <= N; ++i) {
        pos = 1, Min = 9999999999.;
        for (int j = 1; j <= N; ++j) {
            if (!hash[j] && Min - dis[j] > 1e-6) {
                pos = j;
                Min = dis[j];
            }
        }
        hash[pos] = 1;
        if (pos == 2) {
            return dis[2];
        }
        for (int j = 1; j <= N; ++j) {
            double t = max(dis[pos], G[pos][j]);
            if (!hash[j]) {
                dis[j] = min(dis[j], t);
            }
        }
    }
}

int main()
{
    int ca = 0;
    while (scanf("%d", &N), N) {
        memset(G, 0, sizeof (G));
        for (int i = 1; i <= N; ++i) {
            scanf("%d %d", &e[i].x, &e[i].y);
        }
        for (int i = 1; i <= N; ++i) {
            for (int j = 1; j <= N; ++j) {
                G[i][j] = dist(i, j);
            }
        }
        printf("Scenario #%d\n", ++ca);
        printf("Frog Distance = %.3lf\n\n", dijkstra());
    }
    return 0;
}

kruskal版本

#include <cstdlib>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#define MAXN 205
using namespace std;

int N, pos, set[MAXN];

struct Node
{
    int x, y;
    double far;
    bool operator < (Node t) const
    {
        return far < t.far;
    }
}e[40005];

struct {
    int x, y;
}p[205];

inline double dist(int x, int y)
{
    return sqrt(double((p[x].x-p[y].x)*(p[x].x-p[y].x) + (p[x].y-p[y].y)*(p[x].y-p[y].y)));
}

int find(int x)
{
    return set[x] = set[x] == x ? x : find(set[x]);
}

inline void merge(int a, int b)
{
    set[a] = b;
}

int main()
{
    int ca = 0;
    while (scanf("%d", &N), N) {
        pos = 0;
        for (int i = 1; i <= N; ++i) {
            scanf("%d %d", &p[i].x, &p[i].y);
            set[i] = i;
        }
        for (int i = 1; i <= N; ++i) {
            for (int j = i+1; j <= N; ++j) {
                ++pos;
                e[pos].x = i, e[pos].y = j;
                ++pos;
                e[pos].x = j, e[pos].y = i;
                e[pos].far = e[pos-1].far = dist(i, j);
            }
        }
        sort(e+1, e+1+pos);
        for (int i = 1; i <= pos; ++i) {
            int a = find(e[i].x), b = find(e[i].y);
            if (a != b) {
                merge(a, b);
            }
            if (find(1) == find(2)) {
                printf("Scenario #%d\n", ++ca);
                printf("Frog Distance = %.3lf\n\n", e[i].far);
                break;
            }
        }
    }
    return 0;
}

 dfs版本

#include <cstdlib>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#define MAXN 205
#define INF 29999999.
using namespace std;

int N, head[MAXN], pos;
double dis[MAXN];

struct {
    int x, y;
}p[205];

struct edge
{
    int num, next;
    double far;
}e[40005];

inline double dist(int x, int y)
{
    return sqrt(double((p[x].x-p[y].x)*(p[x].x-p[y].x) + (p[x].y-p[y].y)*(p[x].y-p[y].y)));
}

void insert(int x, int y)
{
    ++pos;
    e[pos].next = head[x];
    e[pos].num = y;
    e[pos].far = dist(x, y);
    head[x] = pos;
}

void dfs(int x, double far)
{
    if (x == 2) {
        return;
    }
    for (int i = head[x]; i; i = e[i].next) {
        double t = max(e[i].far, far);
        if (dis[e[i].num]-t > 1e-6) {
            dis[e[i].num] = t;
            dfs(e[i].num, dis[e[i].num]);
        }
    }
}

int main()
{
    int ca = 0;
    while (scanf("%d", &N), N) {
        pos = 0;
        fill(dis, dis+MAXN, INF);
        memset(head, 0, sizeof (head));
        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 = 1; j <= N; ++j) {
                insert(i, j);
            }
        }
        dis[1] = 0.;
        dfs(1, dis[1]);
        printf("Scenario #%d\n", ++ca);
        printf("Frog Distance = %.3lf\n\n", dis[2]);
    } 
    return 0;
}

Floyd版本

#include <cstdlib>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <iostream>
#include <algorithm>
using std::max;
using std::min;
using std::cin;
using std::cout;
using std::endl;

int N;
struct Node {
    int x, y;
}e[205];

double G[205][205];

double dist(const Node & a, const Node & b) {
    return sqrt((a.x-b.x)*(a.x-b.x) + (a.y-b.y)*(a.y-b.y));    
}

void build() {
    for (int i = 1; i <= N; ++i) {
        for (int j = 1; j <= N; ++j) {
            G[i][j] = dist(e[i], e[j]);
        }    
    }    
}

void floyd() {
    for (int k = 1; k <= N; ++k) {
        for (int i = 1; i <= N; ++i) {
            if (i == k) continue;
            for (int j = 1; j <= N; ++j) {
                if (G[i][k] > G[i][j] || G[k][j] > G[i][j] || j == k) continue;
                G[i][j]    = min(G[i][j], max(G[i][k], G[k][j]));
            }    
        }    
    }    
}

int main () {
    int ca = 0;
    while (cin >> N, N) {
        for (int i = 1; i <= N; ++i) {
            cin >> e[i].x >> e[i].y;
        }
        build();
        floyd();
        printf("Scenario #%d\n", ++ca);
        printf("Frog Distance = %.3f\n\n", G[1][2]);
    }
    return 0;
} 

SPFA版本

#include <cstdlib>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <queue>
#define INF 999999999.
#define MAXN 205
using namespace std;
// 该题每两点之间都有边的存在,所以这里用SPFA遍历边的时候并没有什么优势

int N, head[MAXN], pos;
double dis[MAXN];

struct Node
{
    int x, y;
}e[MAXN];

struct Edge
{
    int num, next;
    double far;
}edge[40005];

double dist(int x, int y)
{
    return sqrt(double((e[x].x-e[y].x)*(e[x].x-e[y].x)+(e[x].y-e[y].y)*(e[x].y-e[y].y)));
}

void insert(int x, int y)
{
    ++pos;
    edge[pos].next = head[x];
    edge[pos].num = y;
    edge[pos].far = dist(x, y);
    head[x] = pos;
}double SPFA()
{
    int obj;
    queue<int>q;
    fill(dis, dis+MAXN, INF);
    dis[1] = 0;
    q.push(1);
    while (!q.empty()) {
        obj = q.front();
        q.pop();
        for (int i = head[obj]; i; i = edge[i].next) {
            double t = max(dis[obj], edge[i].far);
            if (t < dis[edge[i].num]) {
                dis[edge[i].num] = t;
                q.push(edge[i].num);
            }
        }
    }
    return dis[2];
}

int main()
{
    int ca = 0;
    while (scanf("%d", &N), N) {
        memset(head, 0, sizeof (head));
        pos = 0; // 由于是静态的边,所以这里需要回溯pos指针
        for (int i = 1; i <= N; ++i) {
            scanf("%d %d", &e[i].x, &e[i].y);
        }
        for (int i = 1; i <= N; ++i) {
            for (int j = 1; j <= N; ++j) {
                insert(i, j);
            }
        }
        printf("Scenario #%d\n", ++ca);
        printf("Frog Distance = %.3lf\n\n", SPFA());
    }
    return 0;
}
原文地址:https://www.cnblogs.com/Lyush/p/2571691.html