[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)的箱子移动 ...
随机推荐
- 暑期——第八周总结(1,安装好hadoop之后访问http://localhost:50070,无法连接【已解决】 2,Hbase命令详解)
所花时间:7天 代码行:800(Java) 博客量:1篇 了解到知识点 : 一:http://localhost:50070无法访问 安装好hadoop之后 输入所有东西都有 可就是访问50070无法 ...
- Spring boot 梳理 - WebMvcConfigurer接口 使用案例
转:https://yq.aliyun.com/articles/617307 SpringBoot 确实为我们做了很多事情, 但有时候我们想要自己定义一些Handler,Interceptor,Vi ...
- java 对数组进行截取组合操作
1.使用skip跳过和limit限制组合,示例: Integer skip = (page.getPageNum() - 1) * page.getPageNum(); Integer limit = ...
- 前端深入之css篇|link和@import到底有什么区别?
写在前面 在真正的前端开发中,我们很少去写行内样式和内嵌样式,通常都是去引用外部样式. 而在我们学习之初的外部样式表都是用link引入的,但是当后来我们学习的逐渐深入,发现@import也可以引入样式 ...
- SpringBoot返回JSON
目录 1.SpringBoot返回JSON简介 2.整合jackson-databind 3.整合Gson 4.整合fastjson 1.SpringBoot返回JSON简介 随着web开发前后端分离 ...
- git一步步上传自己的项目至github,及仓库更新
一.使用git上传项目到github 首先登陆github账号,选择新建一个库,填写项目名称,描述 创建完成之后,跳转到下面的页面,下面红框中的网址要记住,在后面上传代码的时候需要使用 接下来,我们需 ...
- ant path匹配原则
ant path匹配原则 又称路径匹配原则,spring中的相关策略类org.springframework.util.AntPathMatcher 路径模式使用了apache ant的路径样式 ap ...
- 从0开始学FreeRTOS-(列表&列表项)-6
# FreeRTOS列表&列表项的源码解读 第一次看列表与列表项的时候,感觉很像是链表,虽然我自己的链表也不太会,但是就是感觉很像. 在FreeRTOS中,列表与列表项使用得非常多,是Free ...
- Git学习记录-基本命令篇
目录 网页在线练习地址 https://learngitbranching.js.org/ 1.git commit Git 仓库中的提交记录保存的是你的目录下所有文件的快照,就像是把整个目录复制,然 ...
- Tomcat部署项目的三个方法
所需软件安装 要想在Tomcat中部署项目前提是先要搭建好Tomcat,搭建Tomcat就离不开以下软件包的安装配置,本次演示使用Linux平台 1.JDK软件包 JDK是一切java应用程序的基础, ...