[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)的箱子移动 ...
随机推荐
- 实例化Bean的几种方法
1.使用构造器实例化Bean. 当没有指定实例化方法时,Spring IoC容器能使用默认空构造器.构造器实例化包括默认空构造器和有参数构造器两种方式创建Bean. 2.使用构造器实例 ...
- [c++] 面试题之犄角旮旯 第壹章
记录C/C++语言相关的问题. 算法可视化:https://visualgo.net/en <data structure and algorithm in c++> By Adam 有免 ...
- 采用redis生成唯一且随机的订单号
项目描述 最近做的一个项目有这么一个需求:需要生成一个唯一的11位的就餐码(类似于订单号的概念),就餐码的规则是:一共是11位的数字,前面6位是日期比如2019年07月20就是190720,后面五位是 ...
- opencv调整图像亮度对比度
图像处理 图像变换就是找到一个函数,把原始图像矩阵经过函数处理后,转换为目标图像矩阵. 可以分为两种方式,即像素级别的变换和区域级别的变换 Point operators (pixel transfo ...
- tomcat下c3p0连接池配置问题
一.首先如果要使用这个连接池,就需要导入c3p0-0.9.2-pre1.jar架包和支持架包mchange-commons-0.2.jar, 我这里测试使用的是msql数据库 当然也需要导入mysql ...
- 转载:alpha测试和beta测试的区别;黑盒测试和白盒测试的区别;
alpha测试版,有点相当于内部测试,一般开发人员在场 ,是由用户做测试,但开发人员在场,一般是请用户到开发现场去测试 beta测试版,完全交给用户,由用户做测试,返回测试报告,相当于发行前的一个 ...
- F#周报2019年第39期
新闻 宣告F# 4.7 宣告.NET Core 3.0 .NET Core 3.0中ASP.NET Core与Blazor的更新 .NET Conf 2019里提到的ML.NET与模型构建器 参与.N ...
- android字母索引实现ListView定位
最近闲的很,没什么事干 ,在玩手机的时间看到android系统自带的那个通讯录软件对联系人的快速定位功能. 感觉这个功能也比较实用自己就试着自己去实现. 虽然网络上还是有大牛封闭好了的框架,但是如果 ...
- Python攻破淘宝网各类反爬手段,采集淘宝网ZDB(女用)的销量!
声明: 由于某些原因,我这里会用手机代替,其实是一样的! 环境: windows python3.6.5 模块: time selenium re 环境与模块介绍完毕后,就可以来实行我们的操作了. 第 ...
- Shell之Test命令
目录 Shell之Test命令 参考 Test简介 Test语法 表达式之逻辑运算 表达式之字符串判断 表达式之整数判断 表达式之文件判断 Shell之Test命令