题意 : 给出二维平面上 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. Maven install报错:MojoFailureException ,To see the full stack trace of the errors, re-run Maven with the -e switch.解决

    报错日志: SLF4J: Failed to load class "org.slf4j.impl.StaticLoggerBinder".SLF4J: Defaulting to ...

  2. nginx下使用asan和valgrind两个静态检查工具

    1.valgrind valgrind安装:参考:https://blog.csdn.net/justheretobe/article/details/52986461 wegit:http://va ...

  3. delphi SetWindowPos改变窗体位置和状态

    http://blog.163.com/yuanliaofan@126/blog/static/1730690722012534428814/ delphi SetWindowPos改变窗体位置和状态 ...

  4. C++中的通用结构定义,及相应的序列化、反序列化接口

    一个通用的C++结构定义如下: typedef struct tagCommonStruct { long len; void* buff; }CommonStruct_st; 此接口对应的普通序列化 ...

  5. G2 基本使用 折线图 柱状图 饼图 基本配置

    G2的基本使用 1.浏览器引入  <!-- 引入在线资源 --> <script src="https://gw.alipayobjects.com/os/lib/antv ...

  6. 【HANA系列】SAP HANA快捷键大全

    公众号:SAP Technical 本文作者:matinal 原文出处:http://www.cnblogs.com/SAPmatinal/ 原文链接:[HANA系列]SAP HANA快捷键大全   ...

  7. zend studio远程自动上传代码并执行

    http://devzc.com/archives/382/zend_studio_sftp_upload_and_exec/ 最近要做服务的接口测试,公司原有的ide测试工具对于数组的参数化很弱.由 ...

  8. SpringBoot(六) -- SpringBoot错误处理机制

    一.SpringBoot中的默认的错误处理机制 1.在SpringBootWeb开发中,当我们访问请求出现错误时,会返回一个默认的错误页面: 2.在使用其他客户端访问的时候,则返回一个json数据: ...

  9. 到底如何设置 Java 线程池的大小?

    来源:ifeve.com/how-to-calculate-threadpool-size/ 在我们日常业务开发过程中,或多或少都会用到并发的功能.那么在用到并发功能的过程中,就肯定会碰到下面这个问题 ...

  10. Count on a tree SPOJ 10628 主席树+LCA(树链剖分实现)(两种存图方式)

    Count on a tree SPOJ 10628 主席树+LCA(树链剖分实现)(两种存图方式) 题外话,这是我第40篇随笔,纪念一下.<( ̄︶ ̄)↗[GO!] 题意 是说有棵树,每个节点上 ...