POJ 2253 Frogger ( 最短路变形 || 最小生成树 )
题意 : 给出二维平面上 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 ( 最短路变形 || 最小生成树 )的更多相关文章
- POJ 2253 Frogger -- 最短路变形
这题的坑点在POJ输出double不能用%.lf而要用%.f...真是神坑. 题意:给出一个无向图,求节点1到2之间的最大边的边权的最小值. 算法:Dijkstra 题目每次选择权值最小的边进行延伸访 ...
- POJ 2253 Frogger(dijkstra变形)
http://poj.org/problem?id=2253 题意: 有两只青蛙A和B,现在青蛙A要跳到青蛙B的石头上,中间有许多石头可以让青蛙A弹跳.给出所有石头的坐标点,求出在所有通路中青蛙需要跳 ...
- POJ 2253 Frogger 最短路 难度:0
http://poj.org/problem?id=2253 #include <iostream> #include <queue> #include <cmath&g ...
- poj 2253 Frogger(最短路 floyd)
题目:http://poj.org/problem?id=2253 题意:给出两只青蛙的坐标A.B,和其他的n-2个坐标,任一两个坐标点间都是双向连通的.显然从A到B存在至少一条的通路,每一条通路的元 ...
- POJ 2253 Frogger(Dijkstra变形——最短路径最大权值)
题目链接: http://poj.org/problem?id=2253 Description Freddy Frog is sitting on a stone in the middle of ...
- POJ 2253 Frogger (最短路)
Frogger Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 28333 Accepted: 9208 Descript ...
- [ACM] POJ 2253 Frogger (最短路径变形,每条通路中的最长边的最小值)
Frogger Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 24879 Accepted: 8076 Descript ...
- poj 2253 Frogger(floyd变形)
题目链接:http://poj.org/problem?id=1797 题意:给出两只青蛙的坐标A.B,和其他的n-2个坐标,任一两个坐标点间都是双向连通的.显然从A到B存在至少一条的通路,每一条通路 ...
- POJ - 2253 Frogger(Dijkstra变形题)
题意: 题目撰写者的英语真是艰难晦涩,看了别人题解,才知道这题题意. 两个forger 一个froger 要蹦到另外一个froger处,他们的最短距离是这样定义的 : The frog distanc ...
随机推荐
- iView 实战系列教程(21课时)_2.iView 实战教程之导航、路由、鉴权篇
在c盘创建一个iview-router的项目 . 然后使用默认的配置 跳过 添加vue-router的插件 编译我们的文件. 编译好之后,我们启动App 默认的页面就打开了. 默认两个路由一个是abo ...
- 阶段1 语言基础+高级_1-3-Java语言高级_1-常用API_1_第4节 ArrayList集合_12-对象数组
对象数组是怎么回事呢? 新建Person类 代码生成后续的代码 生成一个无参构造 两个成员变量都选上,这是全参构造 生成getter和setter 数组的默认的第几0个元素是null 创建三个对象 输 ...
- delphi开发实例:保存字体设置的方法
http://blog.csdn.net/delphi308/article/details/9906147 delphi开发实例:保存字体设置的方法 2013-08-11 22:37 446人阅读 ...
- Navicat12安装与激活
安装Navicat 1.下载软件和激活工具 链接:https://pan.baidu.com/s/1pFo2BkZYPpPFldG-fhbzIA&shfl=sharepset 提取码:xs97 ...
- assert 与if
strlen的实现用不用加断言(assert)? http://en.cppreference.com/w/cpp/error/assert 自己写strlen实现会加assert判断空指针,Debu ...
- win10编写8086汇编程序(dosbox)
有部分同学反馈.在使用edit命令来编写汇编程序时遇到问题,由于模拟器没有edit程序,所以要换一种方式编写源程序.下面是完整的演示. 视频链接:http://www.bilibili.com/vid ...
- 【AndroidFramework】ATV9遥控器红外模式下,机顶盒在假待机阶段会响应遥控器语音键
[问题描述] 测试部反馈,红外模式下,按power键进入假待机,按红外语音键会唤醒. 背景交代:红外语言键是我们自定义的按键,键值225.在红外模式下按会弹提示框"没连蓝牙,请连蓝牙使用语音 ...
- gdi+ 中发生一般性错误
1.检查文件夹权限 2.保存的文件已存在并因某种原因被锁定. 3.文件夹路径不存在
- 关于微信授权和unionid 的获取思路。
1.首先根据appid 获取到预授权码的code string Appid = "******";//appid.由于网页授权与js-jdk使用不同微信,所以暂时独立于此处. st ...
- 配置OSPF认证
按照上图拓扑配置路由器的IP 配置完后测试直连网段连通性 搭建OSPF网络 注意是多区域的配置,R2是ABR 连着area0和area1 并且每个路由器的环回接口IP也要加进去 此时密码以明文方 ...