[NOIP2013提高组]华容道
这道题第一眼看是暴力,然后发现直接暴力会TLE。
把问题转换一下:移动空格到处跑,如果空格跑到指定位置的棋子,交换位置。
这个可以设计一个状态:$[x1][y1][x2][y2]$,表示空格在$(x1,\ y1)$,棋子在$(x2,\ y2)$的状态,可以向四个方向进行转移。
直接转移,对于每一组询问,都要用 $O(n^4)$ 的时间处理,所以复杂度是 $O(n^4 \times q)$。$70pts$。
观察发现有很多状态是无用状态,只有指定棋子的上下左右四个位置的状态有价值。
然后建个图,会发现不需要在询问时处理,跑一遍最短路,即可AC。
复杂度:$O(n^4)\ +\ O(n^2\ logn \times q)$
#include <iostream>
#include <cstdio>
#include <cstring>
#include <queue> using namespace std; #define re register
#define LL long long
#define rep(i, x, y) for (register int i = x; i <= y; ++i)
#define repd(i, x, y) for (register int i = x; i >= y; --i)
#define maxx(a, b) a = max(a, b)
#define minn(a, b) a = min(a, b)
#define inf 1e9
#define linf 1e17 inline int read() {
re int w = , f = ; char c = getchar();
while (!isdigit(c)) f = c == '-' ? - : f, c = getchar();
while (isdigit(c)) w = (w << ) + (w << ) + (c ^ ), c = getchar();
return w * f;
} const int maxn = + ; struct State {
int x, y, d;
}; queue<State> q; struct Edge {
int u, v, w, pre;
}; inline int convert(int x, int y, int d) {
return x * + y * + d;
} struct Node {
int u, d;
bool operator < (const Node &rhs) const {
return d > rhs.d;
}
}; priority_queue <Node> Q; struct Graph {
Edge edges[maxn * maxn * maxn];
int G[maxn * maxn * maxn], n, m;
int d[maxn * maxn * maxn], vis[maxn * maxn * maxn];
void init(int n) {
this->n = n;
m = ;
memset(G, , sizeof(G));
}
void AddEdge(int u, int v, int w) {
edges[++m] = (Edge){u, v, w, G[u]};
G[u] = m;
}
void dijkstra() {
memset(vis, , sizeof(vis));
while (!Q.empty()) {
re Node head = Q.top(); Q.pop();
int u = head.u;
if (vis[u]) continue;
vis[u] = ;
for (re int i = G[u]; i; i = edges[i].pre) {
Edge &e = edges[i];
if (!vis[e.v] && d[u] + e.w < d[e.v]) {
d[e.v] = d[u] + e.w;
Q.push((Node){e.v, d[e.v]});
}
}
}
}
} G; int fx[] = {, , , -};
int fy[] = {, , -, }; int n, m, t;
int a[maxn][maxn], vis[maxn][maxn], dis[maxn][maxn]; void bfs(int X, int Y) {
memset(dis, 0x3f, sizeof(dis));
dis[X][Y] = ;
q.push((State){X, Y, });
while (!q.empty()) {
State head = q.front(); q.pop();
dis[head.x][head.y] = head.d;
rep(i, , ) {
re int x = head.x + fx[i], y = head.y + fy[i];
if (a[x][y] && !vis[x][y]) {
vis[x][y] = ;
dis[x][y] = head.d + ;
q.push((State){x, y, dis[x][y]});
}
}
}
} int main() {
n = read(), m = read(), t = read(); rep(i, , n)
rep(j, , m)
a[i][j] = read(); G.init(n * n * ); rep(X, , n)
rep(Y, , m)
if (a[X][Y]) {
rep(i, , ) {
re int x = X + fx[i], y = Y + fy[i];
if (a[x][y]) {
memset(vis, , sizeof(vis));
vis[x][y] = vis[X][Y] = ;
bfs(x, y);
rep(j, , ) {
re int x2 = X + fx[j], y2 = Y + fy[j];
if (i == j || !a[x2][y2]) continue;
G.AddEdge(convert(X, Y, i), convert(X, Y, j), dis[x2][y2]);
}
}
}
if (a[X][Y + ]) G.AddEdge(convert(X, Y, ), convert(X, Y + , ), );
if (a[X + ][Y]) G.AddEdge(convert(X, Y, ), convert(X + , Y, ), );
if (a[X][Y - ]) G.AddEdge(convert(X, Y, ), convert(X, Y - , ), );
if (a[X - ][Y]) G.AddEdge(convert(X, Y, ), convert(X - , Y, ), );
} re int Ex, Ey, Sx, Sy, Tx, Ty; while (t--) {
Ex = read(), Ey = read(), Sx = read(), Sy = read(), Tx = read(), Ty = read(); if (Sx == Tx && Sy == Ty) {
printf("0\n");
continue;
} memset(vis, , sizeof(vis));
vis[Ex][Ey] = vis[Sx][Sy] = ;
bfs(Ex, Ey);
memset(G.d, 0x3f, sizeof(G.d));
rep(i, , ) {
Q.push((Node){convert(Sx, Sy, i), dis[Sx + fx[i]][Sy + fy[i]]});
G.d[convert(Sx, Sy, i)] = dis[Sx + fx[i]][Sy + fy[i]];
}
G.dijkstra(); re int ans = inf;
rep(i, , )
if (a[Tx + fx[i]][Ty + fy[i]]) minn(ans, G.d[convert(Tx, Ty, i)]);
if (ans == inf) printf("-1\n");
else printf("%d\n", ans);
} return ;
}
[NOIP2013提高组]华容道的更多相关文章
- [NOIP2013 提高组] 华容道 P1979 洛谷
[NOIP2013 提高组] 华容道 P1979 洛谷 强烈推荐,更好的阅读体验 经典题目:spfa+bfs+转化 题目大意: 给出一个01网格图,和点坐标x,y空格坐标a,b,目标位置tx,ty要求 ...
- [NOIp2013提高组]积木大赛/[NOIp2018提高组]铺设道路
[NOIp2013提高组]积木大赛/[NOIp2018提高组]铺设道路 题目大意: 对于长度为\(n(n\le10^5)\)的非负数列\(A\),每次可以选取一个区间\(-1\).问将数列清零至少需要 ...
- [NOIP2013提高组] CODEVS 3287 火车运输(MST+LCA)
一开始觉得是网络流..仔细一看应该是最短路,再看数据范围..呵呵不会写...这道题是最大生成树+最近公共祖先.第一次写..表示各种乱.. 因为要求运输货物质量最大,所以路径一定是在最大生成树上的.然后 ...
- 【NOIP2013提高组T3】加分二叉树
题目描述 设一个n个节点的二叉树tree的中序遍历为(1,2,3,…,n),其中数字1,2,3,…,n为节点编号.每个节点都有一个分数(均为正整数),记第i个节点的分数为di,tree及它的每个子树都 ...
- NOIP2013 提高组day2 3 华容道 BFS
描述 小 B 最近迷上了华容道,可是他总是要花很长的时间才能完成一次.于是,他想到用编程来完成华容道:给定一种局面,华容道是否根本就无法完成,如果能完成,最少需要多少时间. 小 B 玩的华容道与经典的 ...
- [NOIP2013] 提高组 洛谷P1979 华容道
题目描述 [问题描述] 小 B 最近迷上了华容道,可是他总是要花很长的时间才能完成一次.于是,他想到用编程来完成华容道:给定一种局面, 华容道是否根本就无法完成,如果能完成, 最少需要多少时间. 小 ...
- 洛谷P1979 [NOIP2013提高组Day2T3]华容道
P1979 华容道 题目描述 [问题描述] 小 B 最近迷上了华容道,可是他总是要花很长的时间才能完成一次.于是,他想到用编程来完成华容道:给定一种局面, 华容道是否根本就无法完成,如果能完成, 最少 ...
- 3537. 【NOIP2013提高组day2】华容道(搜索 + 剪枝)
Problem 给出一个类似华容道的图.\(q\)次询问,每次给你起始点,终止点,空格位置,让你求最少步数 \(n,m\le 30, q\le 500\). Soultion 一道智障搜索题. 弱智想 ...
- NOIP2013提高组D2T3 华容道
n<=30 * m<=30 的地图上,0表示墙壁,1表示可以放箱子的空地.q<=500次询问,每次问:当空地上唯一没有放箱子的空格子在(ex,ey)时,把位于(sx,sy)的箱子移动 ...
随机推荐
- python里的while循环和if循环
一.循环的概念 循环是程序设计语言中反复执行某些代码的一种计算机处理过程,常见的有按照次数循环和按条件循环. 二.循环的基本格式 (while循环的基本格式) a=1#定义一个数 while a==1 ...
- 网络编程之多线程——GIL全局解释器锁
网络编程之多线程--GIL全局解释器锁 一.引子 定义: In CPython, the global interpreter lock, or GIL, is a mutex that preven ...
- 使用uEdit时,在线管理图片功能不可用
把所有的配置文件都配置好了,uedit的在线管理功能图片还是不可用,看了一下源码: 是的,它在img的src属性后边的图片上加上了参数,那肯定不能用啊,所以修改源文件image.js.直接搜索noCa ...
- 首次接触flask遇到socket.error: [Errno 10013] 报错
解决方案: 发现是因为端口5000被占用了,设置一个其他port就行:app.run(port=5050)
- MySql错误处理--错误代码和消息
附录B:错误代码和消息 目录 B.1. 服务器错误代码和消息 B.2. 客户端错误代码和消息 本章列出了当你用任何主机语言调用MySQL时可能出现的错误.首先列出了服务器错误消息.其次列出了客户端 ...
- CentOS6.x环境通过yum命令在线安装或重装zookeeper-server
一.环境描述: 在CentOS6.x系统环境下,使用yum命令的形式安装zookeeper-server,由于我这里是重新安装zookeeper-server,所以在正式开始之前我需要将原本的zook ...
- 【django】form
form 组件组要功能: 生成HTML标签 验证用户数据(显示错误信息) HTML Form提交保留上次提交数据 初始化页面显示内容 1.创建Form类时,主要涉及到 [字段] 和 [插件],字段用于 ...
- java8 base64使用
java 1.8中引入了Base64,不在需要引入第三方库就可以使用base64了. 在需要用到base64进行加密解密的时候就可以使用了 String text = "base64 in ...
- 分库分表(3) ---SpringBoot + ShardingSphere 实现读写分离
分库分表(3)---ShardingSphere实现读写分离 有关ShardingSphere概念前面写了两篇博客: 1.分库分表(1) --- 理论 2. 分库分表(2) --- ShardingS ...
- Mysql存储引擎以及锁机制
一.常用命令 1.查看引擎(默认为InnoDB) 查看mysql提供的存储引擎:show engienes 查看mysql当前默认的存储引擎:show variables like '%storage ...