Luogu 1979 [NOIP2013] 华容道
要优先安排历年NOIP题
考虑到要移动,肯定要先把空的格子移动到起点旁边,所以我们对于每一个询问都先bfs一次求出把空格移到起点的四个位置的最短路,而且要保证不能移动起点的方块。
只有空的格子在一个格子四边的时候才可以进行一次移动,所以将一个可行的格子与它周围四个可能的空格出现位置捆绑为一个结点,这样通过移动空格或者把格子移到空格上都可以转移到下一个点。
对于移动格子的边,只要扫一遍判一下合法就可以连上一条为1的边,剩下的可以采取预处理的策略先bfs一遍然后处理空格在一个格子四周移动时的最小位置,bfs的时候注意不能移动当前找到的格子。
这样子一共最多有$n * n * 4 = 900$个点,每一个点搜一遍的时间上界是$n * n * 4 * n * n = O(n ^ {4})$级别的。
对于每一个询问,只要先bfs一遍求出把空格移到起点四边的最短路线,然后丢到队列里跑个最短路就可以了。
还是多写写堆dij吧,戒掉spfa
这样子最后的答案就是终点四周的格子编号的最小值。
注意到bfs函数可以重复利用。
时间复杂度$O((nm)^{2} + q(nm)^{2})$。
Code:
#include <cstdio>
#include <cstring>
#include <queue>
using namespace std; const int L = ;
const int N = ;
const int M = 1e6 + ;
const int inf = 0x3f3f3f3f;
const int dx[] = {-, , , };
const int dy[] = {, , , -}; int n, m, qn, tot, head[N], d[N], a[L][L], dis[L][L];
bool vis[N]; struct Edge {
int to, nxt, val;
} e[M]; inline void add(int from, int to, int val) {
e[++tot].to = to;
e[tot].val = val;
e[tot].nxt = head[from];
head[from] = tot;
} inline void read(int &X) {
X = ;
char ch = ;
int op = ;
for(; ch > ''|| ch < ''; ch = getchar())
if(ch == '-') op = -;
for(; ch >= '' && ch <= ''; ch = getchar())
X = (X << ) + (X << ) + ch - ;
X *= op;
} struct Node {
int x, y;
Node(int nowx = , int nowy = ) : x(nowx), y(nowy) {} inline void readIn() {
read(x), read(y);
}
}; inline int id(Node now, int sta) {
return ((now.x - ) * m + now.y - ) * + sta + ;
} void bfs(Node st, Node ed, int sta) {
queue <Node> Q; Q.push(st);
memset(dis, , sizeof(dis)); dis[st.x][st.y] = ; for(; !Q.empty(); ) {
Node out = Q.front(); Q.pop();
for(int i = ; i < ; i++) {
Node in = Node(out.x + dx[i], out.y + dy[i]);
if(!a[in.x][in.y] || (in.x == ed.x && in.y == ed.y) || dis[in.x][in.y]) continue;
dis[in.x][in.y] = dis[out.x][out.y] + ;
Q.push(in);
}
} if(sta == ) return;
for(int i = ; i < ; i++) {
int tox = ed.x + dx[i], toy = ed.y + dy[i];
if((tox == st.x && toy == st.y) || !dis[tox][toy]) continue;
add(id(ed, sta), id(ed, i), dis[tox][toy] - );
}
add(id(ed, sta), id(st, (sta + ) % ), );
} void spfa(Node st, Node ed) {
queue <int> Q;
memset(d, 0x3f, sizeof(d)); for(int i = ; i < ; i++) {
int tox = st.x + dx[i], toy = st.y + dy[i];
if(!dis[tox][toy]) continue;
int now = id(st, i);
Q.push(now);
d[now] = dis[tox][toy] - ;
vis[now] = ;
} for(; !Q.empty(); ) {
int x = Q.front(); Q.pop();
vis[x] = ;
for(int i = head[x]; i; i = e[i].nxt) {
int y = e[i].to;
if(d[y] > d[x] + e[i].val) {
d[y] = d[x] + e[i].val;
if(!vis[y]) {
vis[y] = ;
Q.push(y);
}
}
}
} int ans = inf;
for(int i = ; i < ; i++)
ans = min(ans, d[id(ed, i)]);
if(ans == inf) puts("-1");
else printf("%d\n", ans);
} int main() {
read(n), read(m), read(qn);
for(int i = ; i <= n; i++)
for(int j = ; j <= m; j++)
read(a[i][j]); for(int i = ; i <= n; i++)
for(int j = ; j <= m; j++) {
if(!a[i][j]) continue;
for(int k = ; k < ; k++) {
int tox = i + dx[k], toy = j + dy[k];
if(a[tox][toy]) bfs(Node(tox, toy), Node(i, j), k);
}
} for(Node bla, st, ed; qn--; ) {
bla.readIn(), st.readIn(), ed.readIn();
if(st.x == ed.x && st.y == ed.y) {
puts("");
continue;
}
bfs(bla, st, );
spfa(st, ed);
} return ;
}
Luogu 1979 [NOIP2013] 华容道的更多相关文章
- luogu P1979 [NOIP2013] 华容道
传送门 这道题中,棋子的移动是要移动到空格上去,所以空格要在棋子旁边才能移动棋子;而棋子移动的方向由空格决定 所以我们可以记三维状态\(di_{i,j,k}\),表示状态为棋子在\((i,j)\),空 ...
- Luogu 1979 NOIP 2013 华容道(搜索,最短路径)
Luogu 1979 NOIP 2013 华容道(搜索,最短路径) Description 小 B 最近迷上了华容道,可是他总是要花很长的时间才能完成一次.于是,他想到用编程来完成华容道:给定一种局面 ...
- Luogu 1970 NOIP2013 花匠 (贪心)
Luogu 1970 NOIP2013 花匠 (贪心) Description 花匠栋栋种了一排花,每株花都有自己的高度.花儿越长越大,也越来越挤.栋栋决定把这排中的一部分花移走,将剩下的留在原地,使 ...
- [Luogu 1967] NOIP2013 货车运输
[Luogu 1967] NOIP2013 货车运输 一年多前令我十分头大的老题终于可以随手切掉了- 然而我这码风又变毒瘤了,我也很绝望. 看着一年前不带类不加空格不空行的清纯码风啊,时光也好像回去了 ...
- LOJ2613 NOIP2013 华容道 【最短路】*
LOJ2613 NOIP2013 华容道 LINK 这是个好题,具体题意比较麻烦可以直接看LINK中的链接 然后考虑我们可能的移动方式 首先我们需要把白块移动到需要移动块S的附近(附近四格) 然后我们 ...
- [NOIP2013]华容道 题解(搜索)
[NOIP2013]华容道 [题目描述] 这道题根据小时候玩华容道不靠谱的经验还以为是并查集,果断扑街.考后想想也是,数据这么小一定有他的道理. 首先由于是最小步数,所以BFS没跑了.那么我们大可把这 ...
- [NOIP2013]华容道 题解
[NOIP2013]华容道 首先是一种比较显然的做法. 整个棋盘,除了起点,终点和空格,其他的方块是等价的. 对于终点,它始终不会变化,如果搜到终点结束搜索即可,所以我们不需要考虑终点. 所以需要考虑 ...
- [NOIP2013]华容道
1.题面 小 B 最近迷上了华容道,可是他总是要花很长的时间才能完成一次.于是,他想到用编程来完成华容道:给定一种局面,华容道是否根本就无法完成,如果能完成,最少需要多少时间.小 B 玩的华容道与经典 ...
- [luogu P1967][NOIp2013] 货车运输
题目描述 A 国有 n 座城市,编号从 1 到 n,城市之间有 m 条双向道路.每一条道路对车辆都有重量限制,简称限重.现在有 q 辆货车在运输货物, 司机们想知道每辆车在不超过车辆限重的情况下,最多 ...
随机推荐
- python list的extend和append方法
append: Appends object at the end. x = [1, 2, 3] x.append([4, 5]) print (x) gives you: [1, 2, 3, [4, ...
- NET Core 2.0利用MassTransit集成RabbitMQ
NET Core 2.0利用MassTransit集成RabbitMQ https://www.cnblogs.com/Andre/p/9579764.html 在ASP.NET Core上利用Mas ...
- 畅通工程(自己写的BFS,但后面想了下并查集更好更快)
某省调查城镇交通状况,得到现有城镇道路统计表,表中列出了每条道路直接连通的城镇.省政府“畅通工程”的目标是使全省任何两个城镇间都可以实现交通(但不一定有直接的道路相连,只要互相间接通过道路可达即可). ...
- RabbitMQ集群 Docker一键部署
以下内容来自网络转载 步骤1. 安装docker 以centos7为例,https://docs.docker.com/engine/installation/linux/centos/ 步骤2. 创 ...
- C++语言对C的增强(1)——实用性、变量检测、struct类型、C++中所有变量和函数都必须有类型、bool类型、三目运算符
1.“实用性”增强 C语言中的变量都必须在作用域开始的位置定义,C++中更强调语言的“实用性”,所有的变量都可以在需要使用时再定义. 2.变量检测加强 在C语言中,重复定义多个同名的全局变量是合法的: ...
- Unity Shader 创建程序纹理贴图
创建一个脚本 附加到一个游戏体上 using UnityEngine;using System.Collections; public class ProceduralTexture : MonoBe ...
- 使用.NET中的XML注释(二) -- 创建帮助文档入门篇
一.摘要 在本系列的第一篇文章介绍了.NET中XML注释的用途, 本篇文章将讲解如何使用XML注释生成与MSDN一样的帮助文件.主要介绍NDoc的继承者:SandCastle. 二.背景 要生成帮助文 ...
- http协议及原理分析 1
1:200与304的区别 浏览器第一次加载成功返回200状态,并会在浏览器的缓存中记录下 max-age 这个值.第二次发起服务器的访问时 会先看缓存中有没有要加载的资源 如果有 再去看有没有超出 m ...
- CentOS6.5 下MySQL傻瓜式安装
为了为服务器上装mysql我先在虚拟机上练习了一下特此记录并分享; 注:参考文章https://www.cnblogs.com/xiaoluo501395377/archive/2013/04/07/ ...
- Angular5学习笔记 - 创建组件(四)
一.创建组件 ng generate component component-name #简写 ng g c component-name ng generate directive|pipe|ser ...