洛谷 P3831 [SHOI2012]回家的路
时间:2019-09-13
本文章向大家介绍洛谷 P3831 [SHOI2012]回家的路,主要包括洛谷 P3831 [SHOI2012]回家的路使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。
洛谷 P3831 [SHOI2012]回家的路
题目:
- 有图。转链接
题解:
- 分层图。
- 挺不错的,进一步理解了分层图。
- 分层图就是把所有图中的状态都表示出来,并且不同状态之间互不干扰。也就是说如果有一个问题可以用方法一解决或者方法二解决,那么分层图就可以使得不是用方法一就是用方法二,不会出现两种方法都取到的紊乱情况。
- 此题题意:一个网格图,横竖走一条边用时 2,只能在特定点转向,横竖转向用时 1,问两点最短用时。
- 因为只有走到标记的点才能转方向,也就是说,从起点到终点一定要经过标记的点才能到达(起点和终点也算标记点)。那么我们考虑的范围就只是标记的点之间的关系。
- 对于标记的点,是可以转方向的。
- 此题的决策为转向,由于只存在横向和纵向两个方向,我们对这两个方向分别建立一层。即一层只连原图横向边,一层只连纵向边。
- 然后第一层和第二层相同的点连一条权值为1的边,表示从横向走变成纵向走需要1的代价。
- 最后跑最短路即可。
#include <iostream>
#include <cstdio>
#include <cmath>
#include <cstring>
#include <queue>
#include <algorithm>
#define N 1000005
#define M 1000005
using namespace std;
struct Node
{
int val, pos;
friend bool operator < (Node x, Node y) {
return x.val > y.val;
}
};
struct E {int next, to, dis;} e[M];
struct A {int x, y, id;} a[N];
int n, m, num;
int h[N], dis[N];
bool vis[N];
int read()
{
int x = 0; char c = getchar();
while(c < '0' || c > '9') c = getchar();
while(c >= '0' && c <= '9') {x = x * 10 + c - '0'; c = getchar();}
return x;
}
bool cmp1(A u, A v)
{
if(u.x == v.x) return u.y < v.y;
return u.x < v.x;
}
bool cmp2(A u, A v)
{
if(u.y == v.y) return u.x < v.x;
return u.y < v.y;
}
void add(int u, int v, int w)
{
e[++num].next = h[u];
e[num].to = v;
e[num].dis = w;
h[u] = num;
}
int main()
{
cin >> n >> m;
n = m + 2;
for(int i = 1; i <= n; i++)
{
a[i].x = read();
a[i].y = read();
a[i].id = i;
}
sort(a + 1, a + 1 + n, cmp1);
for(int i = 2; i <= n; i++)
if(a[i - 1].x == a[i].x)
{
add(a[i - 1].id, a[i].id, (a[i].y - a[i - 1].y) * 2);
add(a[i].id, a[i - 1].id, (a[i].y - a[i - 1].y) * 2);
}
sort(a + 1, a + 1 + n, cmp2);
for(int i = 2; i <= n; i++)
if(a[i - 1].y == a[i].y)
{
add(a[i - 1].id + n, a[i].id + n, (a[i].x - a[i - 1].x) * 2);
add(a[i].id + n, a[i - 1].id + n, (a[i].x - a[i - 1].x) * 2);
}
for(int i = 1; i <= n; i++)
add(i, i + n, 1), add(i + n, i, 1);
add(n - 1, n - 1 + n, 0);
add(n - 1 + n, n - 1, 0);
add(n, n + n, 0);
add(n + n, n, 0);
memset(dis, 0x3f, sizeof(dis));
priority_queue<Node> que;
dis[n - 1] = 0, que.push((Node){0, n - 1});
while(que.size())
{
int now = que.top().pos;
que.pop();
if(vis[now]) continue;
vis[now] = 1;
for(int i = h[now]; i != 0; i = e[i].next)
if(dis[now] + e[i].dis < dis[e[i].to])
{
dis[e[i].to] = dis[now] + e[i].dis;
que.push((Node){dis[e[i].to], e[i].to});
}
}
if(dis[n] == 0x3f3f3f3f && dis[n + n] == 0x3f3f3f3f)
{cout << -1; return 0;}
cout << min(dis[n], dis[n + n]);
return 0;
}
原文地址:https://www.cnblogs.com/BigYellowDog/p/11516707.html
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- 做一个简单的京东购物栏
- 解决Elasticsearch SQL命令行启动报错 ./x-pack-env: No such file or directory
- MySql 入门到精通-sql查询语句的执行过程,你真的知道吗?
- 用 float 存储金额,老板说损失从工资里扣!
- 分布式追踪实战
- python的接班者之coconut
- Docker 垃圾回收机制补充
- 通过docker image 获取到 dockerfile
- Tensorflow2.0实现简单的RNN文本分析
- 利用Tensorflow2.0实现手写数字识别
- PyTorch,TensorFlow和NumPy中Stack Vs Concat | PyTorch系列(二十四)
- 为什么大家都说“SELECT *”效率低?
- 手把手教你如何搭建一套GPS定位系统平台
- [较难]LeetCode-4.寻找两个正序数组的中位数 利用数组扩充和二分法切割思想实现
- Go Errors 错误处理