题意 : 给出二维平面上 N 个点,前两个点为起点和终点,问你从起点到终点的所有路径中拥有最短两点间距是多少。

分析 :

① 考虑最小生成树中 Kruskal 算法,在建树的过程中贪心的从最小的边一个个添加,每添加一条边就用用并查集判断起点和终点是否已经连接起来,如果连接起来了,那么答案就是这条边,否则继续添加边。最小生成树最后肯定能保证起点和终点连接起来,因为其是从最小边贪起,所以此方法是正确的!

#include<stdio.h>
#include<algorithm>
#include<math.h>
using namespace std;
;//最大点数
int c[maxn], N;//并查集使用
int cnt;

struct POINT{ int x, y; }Point[maxn];
struct EDGE{
    int from, to;
    double w;
    bool operator < (const EDGE &rhs) const{
        return this->w < rhs.w;
    };
}Edge[maxn*maxn];//储存边的信息,包括起点/终点/权值

double GetDis(const POINT &A, const POINT &B)
{
    double x1 = A.x, x2 = B.x;
    double y1 = A.y, y2 = B.y;
    return (x1-x2)*(x1-x2) + (y1-y2)*(y1-y2);
}

inline void init()
{
    ; i<=N; i++)
        c[i] = i;
    cnt = ;
}

inline void AddEdge(int from, int to, double weight)
{
    Edge[cnt].from = from;
    Edge[cnt].to   = to;
    Edge[cnt].w    = weight;
    cnt++;
}

int Findset(int x)
{
    int root = x;
    while(c[root] != root)
        root = c[root];

    int idx;
    while(c[x] != root){ /// 路径压缩
        idx = c[x];
        c[x] = root;
        x = idx;
    }
    return root;
}

double Kruskal()
{
    sort(Edge,Edge+cnt);
    ;i<cnt;i++){
        int R1 = Findset(Edge[i].from);
        int R2 = Findset(Edge[i].to);
        if(R1 != R2) c[R1]=R2;
        ) == Findset(N)) return Edge[i].w;///判断起点和终点是否连通
    }

}

int main()
{
    ;
    while(~scanf("%d", &N) && N){
        init();
        int x, y;
        scanf(].x, &Point[].y);
        scanf("%d %d", &Point[N].x, &Point[N].y);
        ; i<N; i++)
            scanf("%d %d", &Point[i].x, &Point[i].y);
        ; i<=N; i++){
            ; j<=N; j++){
                double DIS = GetDis(Point[i], Point[j]);
                AddEdge(i, j, DIS);
                AddEdge(j, i, DIS);
            }
        }
        printf("Scenario #%d\n", Case++);
        printf("Frog Distance = %.3f\n\n",  sqrt(Kruskal()) );
    }
    ;
}

② 从最短路算法角度考虑,在 Dijkstra 中不再将保存的 Dis[i] 作为从源点到 i 点的最短距离,而是将其变成从源点到 i 点所有的路径中最短的两点间距,最后松弛条件根据 DP 意义进行修改即可,具体看代码实现。

因为数据不大,所以可以用 Floyd 做,同样是将 DP[i][j] 的意义变成从 i 到 j 中所有路径拥有最短两点间距的距离是多少、转移方程为 DP[i][j] = min( DP[i][j], max( DP[i][k], DP[k][j] ) )

#include<stdio.h>
#include<algorithm>
#include<math.h>
using namespace std;
const double INF  = 1e20;
;

struct POINT{ int x, y; }Point[maxn];
bool vis[maxn];
double G[maxn][maxn], Dis[maxn];
int N;

double GetDis(const POINT &A, const POINT &B)
{
    double x1 = (double)A.x, x2 = (double)B.x;
    double y1 = (double)A.y, y2 = (double)B.y;
    return (x1-x2)*(x1-x2) + (y1-y2)*(y1-y2);
}

double Dijkstra(int st)
{
    ;i<=N;i++)
        Dis[i]=G[st][i],
        vis[i]=false;

    Dis[st]=,
    vis[st]=true;

    int v;
    ; i<N; i++){
        double MinEdge = INF;

        ; j<=N; j++){
            if(!vis[j] && MinEdge > Dis[j]){ ///找出最小的两点间距点以及其终点v
                MinEdge = Dis[j];
                v = j;
            }
        } if(MinEdge == INF) break; ///所有的 vis 都为 true

        vis[v] = true; ///用 v 去松弛其他与它连接的点、更新最优值
        ; j<=N; j++){
            if(!vis[j])
                Dis[j] = min(Dis[j], max(Dis[v], G[v][j])); ///用与 v 相连的点的值来更新最优值、或者被更新
        }
    }

    return Dis[N];
}

int main(void)
{
    ;
    while(~scanf("%d", &N) && N){
        int x, y;
        scanf(].x, &Point[].y);
        scanf("%d %d", &Point[N].x, &Point[N].y);
        ; i<N; i++)
            scanf("%d %d", &Point[i].x, &Point[i].y);

        ; i<=N; i++){
            ; j<=N; j++)
                if(i != j) G[i][j] = G[j][i] = GetDis(Point[i], Point[j]);
                ;
        }
        printf("Scenario #%d\n", Case++);
        printf()) );
    }
    ;
}

Dijkstra

#include<stdio.h>
#include<algorithm>
#include<math.h>
using namespace std;
const double INF  = 1e20;
;

struct POINT{ int x, y; }Point[maxn];
double G[maxn][maxn];
int N;

double GetDis(const POINT &A, const POINT &B)
{
    double x1 = (double)A.x, x2 = (double)B.x;
    double y1 = (double)A.y, y2 = (double)B.y;
    return (x1-x2)*(x1-x2) + (y1-y2)*(y1-y2);
}

int main(void)
{
    ;
    while(~scanf("%d", &N) && N){
        int x, y;
        scanf(].x, &Point[].y);
        scanf("%d %d", &Point[N].x, &Point[N].y);
        ; i<N; i++)
            scanf("%d %d", &Point[i].x, &Point[i].y);

        ; i<=N; i++){
            for(int j=i; j<=N; j++)
                if(i == j) G[i][j] = GetDis(Point[i], Point[j]);
                else G[i][j] = G[j][i] = GetDis(Point[i], Point[j]);
        }

        ; k<=N; k++)
            ; i<=N; i++)
                ; j<=N; j++)
                    G[i][j] = min(G[i][j], max(G[i][k], G[k][j]));

        printf("Scenario #%d\n", Case++);
        printf(][N]));
    }
    ;
}

Floyd

瞎 : 这是接触到的第一道最短路变形问题,我的理解就是最短路的动态规划算法或者思想不止可以用于求解最短路,例如 Dijkstra 最常规的就是用来求解源点到其他点的最短距离、而这里求的是从源点到其他点的所有路径中最小or最大的两顶点点间距离,改变了其DP意义,当然所求的东西也要满足拥有最优子结构!

POJ 2253 Frogger ( 最短路变形 || 最小生成树 )的更多相关文章

  1. POJ 2253 Frogger -- 最短路变形

    这题的坑点在POJ输出double不能用%.lf而要用%.f...真是神坑. 题意:给出一个无向图,求节点1到2之间的最大边的边权的最小值. 算法:Dijkstra 题目每次选择权值最小的边进行延伸访 ...

  2. POJ 2253 Frogger(dijkstra变形)

    http://poj.org/problem?id=2253 题意: 有两只青蛙A和B,现在青蛙A要跳到青蛙B的石头上,中间有许多石头可以让青蛙A弹跳.给出所有石头的坐标点,求出在所有通路中青蛙需要跳 ...

  3. POJ 2253 Frogger 最短路 难度:0

    http://poj.org/problem?id=2253 #include <iostream> #include <queue> #include <cmath&g ...

  4. poj 2253 Frogger(最短路 floyd)

    题目:http://poj.org/problem?id=2253 题意:给出两只青蛙的坐标A.B,和其他的n-2个坐标,任一两个坐标点间都是双向连通的.显然从A到B存在至少一条的通路,每一条通路的元 ...

  5. POJ 2253 Frogger(Dijkstra变形——最短路径最大权值)

    题目链接: http://poj.org/problem?id=2253 Description Freddy Frog is sitting on a stone in the middle of ...

  6. POJ 2253 Frogger (最短路)

    Frogger Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 28333   Accepted: 9208 Descript ...

  7. [ACM] POJ 2253 Frogger (最短路径变形,每条通路中的最长边的最小值)

    Frogger Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 24879   Accepted: 8076 Descript ...

  8. poj 2253 Frogger(floyd变形)

    题目链接:http://poj.org/problem?id=1797 题意:给出两只青蛙的坐标A.B,和其他的n-2个坐标,任一两个坐标点间都是双向连通的.显然从A到B存在至少一条的通路,每一条通路 ...

  9. POJ - 2253 Frogger(Dijkstra变形题)

    题意: 题目撰写者的英语真是艰难晦涩,看了别人题解,才知道这题题意. 两个forger 一个froger 要蹦到另外一个froger处,他们的最短距离是这样定义的 : The frog distanc ...

随机推荐

  1. history历史记录在AJAX下出现异常跳转 [解决]

    事情是这样的,在一个历史记录指针应该在[1, 2, 3, 4]的[3]位置的情况下,出现了历史记录指针指向了[4]的情况,而且是在正常后退事件发生之后,(据我所知)没有代码操作的情况发生的. 这是一个 ...

  2. python常用包官网

    Pandas http://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.Series.reset_index.html?high ...

  3. Vue中解决路由切换,页面不更新的实用方法

    前言:vue-router的切换不同于传统的页面的切换.路由之间的切换,其实就是组件之间的切换,不是真正的页面切换.这也会导致一个问题,就是引用相同组件的时候,会导致该组件无法更新,也就是我们口中的页 ...

  4. 06 使用bbed提交delete的数据--01

    使用bbed模拟delete提交操作 --session 1 TEST@ orcl )); Table created. TEST@ orcl ,'AAAAA'); row created. TEST ...

  5. idea的类头注释和方法注释的编辑

    一:配置类头注释 1:点击file,点击settings 2:点击editor,选择 file and code template ,然后看右侧部分点击include,之后选中File Header ...

  6. 【USACO18JAN】MooTube

    原文链接:https://blog.csdn.net/Patrickpwq/article/details/86656456 给定一棵n个点的树(n=1e5),有边权, 两点间距离定义为两点路径上的 ...

  7. discover面试

    电话面 英语 20191009 面试我的是一个小姐姐,她是数据挖掘分析师,声音很甜很好听.全程英文 (1)please introduce yourself in two minutes (2)我对你 ...

  8. 干货!小白入门Python数据科学全教程

    前言 本文讲解了从零开始学习Python数据科学的全过程,涵盖各种工具和方法 你将会学习到如何使用python做基本的数据分析 你还可以了解机器学习算法的原理和使用 说明 先说一段题外话.我是一名数据 ...

  9. Hdu 4578 Transformation (线段树 分类分析)

    Transformation Time Limit: 15000/8000 MS (Java/Others)    Memory Limit: 65535/65536 K (Java/Others)T ...

  10. SpringDataJPA使用

    一.简介 SpringDataJpa是 JPA规范的一个很好的实现,简化了开发的复杂度,极大提升了开发的效率.SpringDataJpa通过 Repository接口及子接口可以很方便的实现持久化操作 ...