分析

一个比较显然的方式是

设 \(f_{i,j,x,y}\) 表示达到空格所处位置为 \((i,j)\) 且特殊格位置为 \(x,y\) 的状态的最少步数

一次可以交换空格和相邻格,代价为 \(1\),\(bfs\) 转移即可

但确实时间无法接受

我们想到转移时

当且仅当空格和特殊格相邻时特殊格的位置才可能变

所以我们设 \(f_{i,j,k}\) 表示特殊格位置为 \((i,j)\) 且空格在特殊格 \(k(k\in[0,3])\) 方向的最小步数

那么考虑两种转移

1.不动特殊格,空格从 \(k\) 方向转到 \(l\) 方向

2.空格与特殊格交换

第一种可以 \(bfs\) 预处理出来,记为 \(g_{i,j,k,l}\)

第二种代价为 \(1\)

因为有两种代价,所以我们要 \(spfa\) 转移

交换空格会使空格所在特殊格的方向相反

为方便表示我们用 \({1,2,3,4}\) 表示上下左右

\(Code\)

#include<cstdio>
#include<iostream>
#include<cstring>
using namespace std; const int N = 35, INF = 0x3f3f3f3f;
int n, m, q, a[N][N], f[N][N][5], g[N][N][5][5], dis[N][N], vis[N][N][5];
int fx[4][2] = {{-1, 0}, {1, 0}, {0, -1}, {0, 1}};
struct node{int x, y, k;}Q[N*N*N]; inline int judge(int x, int y){return (x >= 1 && x <= n && y >= 1 && y <= m && a[x][y]);} inline int bfs(int sx, int sy, int tx, int ty)
{
memset(dis, 0x3f3f3f3f, sizeof dis);
if (!judge(sx, sy) || !judge(tx, ty)) return INF;
dis[sx][sy] = 0;
int head = 0, tail = 1;
Q[1] = node{sx, sy, 0};
while (head < tail)
{
node now = Q[++head];
if (dis[tx][ty] != INF) return dis[tx][ty];
for(register int k = 0; k < 4; k++)
{
int x = now.x + fx[k][0], y = now.y + fx[k][1];
if (judge(x, y) && dis[x][y] > dis[now.x][now.y] + 1)
dis[x][y] = dis[now.x][now.y] + 1, Q[++tail] = node{x, y, 0};
}
}
return dis[tx][ty];
} void prepare()
{
for(register int i = 1; i <= n; i++)
for(register int j = 1; j <= m; j++)
{
int tmp = a[i][j];
a[i][j] = 0;
for(register int k = 0; k < 4; k++)
for(register int l = 0; l < 4; l++)
g[i][j][k][l] = bfs(i + fx[k][0], j + fx[k][1], i + fx[l][0], j + fx[l][1]);
a[i][j] = tmp;
}
} inline int spfa(int sx, int sy, int tx, int ty)
{
memset(vis, 0, sizeof vis);
int head = 0, tail = 0;
for(register int k = 0; k < 4; k++)
{
int x = sx + fx[k][0], y = sy + fx[k][1];
if (judge(x, y)) Q[++tail] = node{sx, sy, k}, vis[sx][sy][k] = 1;
}
while (head < tail)
{
node now = Q[++head];
for(register int k = 0; k < 4; k++)
{
int x = now.x + fx[k][0], y = now.y + fx[k][1];
if (judge(x, y) && f[x][y][k ^ 1] > f[now.x][now.y][now.k] + g[now.x][now.y][now.k][k] + 1)
{
f[x][y][k ^ 1] = f[now.x][now.y][now.k] + g[now.x][now.y][now.k][k] + 1;
if (!vis[x][y][k ^ 1]) Q[++tail] = node{x, y, k ^ 1}, vis[x][y][k ^ 1] = 1;
}
}
vis[now.x][now.y][now.k] = 0;
}
int ans = INF;
for(register int k = 0; k < 4; k++) ans = min(ans, f[tx][ty][k]);
return (ans == INF ? -1 : ans);
} inline int solve()
{
int ex, ey, sx, sy, tx, ty;
scanf("%d%d%d%d%d%d", &ex, &ey, &sx, &sy, &tx, &ty);
if (!judge(sx, sy) || !judge(tx, ty)) return -1;
if (sx == tx && sy == ty) return 0;
memset(f, 0x3f3f3f3f, sizeof f);
int tmp = a[sx][sy];
a[sx][sy] = 0;
for(register int k = 0; k < 4; k++)
f[sx][sy][k] = bfs(ex, ey, sx + fx[k][0], sy + fx[k][1]);
a[sx][sy] = tmp;
return spfa(sx, sy, tx, ty);
} int main()
{
scanf("%d%d%d", &n, &m, &q);
for(register int i = 1; i <= n; i++)
for(register int j = 1; j <= m; j++) scanf("%d", &a[i][j]);
prepare();
for(register int i = 1; i <= q; i++) printf("%d\n", solve());
}

【NOIP2013提高组】华容道的更多相关文章

  1. [NOIP2013 提高组] 华容道 P1979 洛谷

    [NOIP2013 提高组] 华容道 P1979 洛谷 强烈推荐,更好的阅读体验 经典题目:spfa+bfs+转化 题目大意: 给出一个01网格图,和点坐标x,y空格坐标a,b,目标位置tx,ty要求 ...

  2. [NOIP2013提高组]华容道

    这道题第一眼看是暴力,然后发现直接暴力会TLE. 把问题转换一下:移动空格到处跑,如果空格跑到指定位置的棋子,交换位置. 这个可以设计一个状态:$[x1][y1][x2][y2]$,表示空格在$(x1 ...

  3. [NOIp2013提高组]积木大赛/[NOIp2018提高组]铺设道路

    [NOIp2013提高组]积木大赛/[NOIp2018提高组]铺设道路 题目大意: 对于长度为\(n(n\le10^5)\)的非负数列\(A\),每次可以选取一个区间\(-1\).问将数列清零至少需要 ...

  4. [NOIP2013提高组] CODEVS 3287 火车运输(MST+LCA)

    一开始觉得是网络流..仔细一看应该是最短路,再看数据范围..呵呵不会写...这道题是最大生成树+最近公共祖先.第一次写..表示各种乱.. 因为要求运输货物质量最大,所以路径一定是在最大生成树上的.然后 ...

  5. 【NOIP2013提高组T3】加分二叉树

    题目描述 设一个n个节点的二叉树tree的中序遍历为(1,2,3,…,n),其中数字1,2,3,…,n为节点编号.每个节点都有一个分数(均为正整数),记第i个节点的分数为di,tree及它的每个子树都 ...

  6. NOIP2013 提高组day2 3 华容道 BFS

    描述 小 B 最近迷上了华容道,可是他总是要花很长的时间才能完成一次.于是,他想到用编程来完成华容道:给定一种局面,华容道是否根本就无法完成,如果能完成,最少需要多少时间. 小 B 玩的华容道与经典的 ...

  7. [NOIP2013] 提高组 洛谷P1979 华容道

    题目描述 [问题描述] 小 B 最近迷上了华容道,可是他总是要花很长的时间才能完成一次.于是,他想到用编程来完成华容道:给定一种局面, 华容道是否根本就无法完成,如果能完成, 最少需要多少时间. 小 ...

  8. 洛谷P1979 [NOIP2013提高组Day2T3]华容道

    P1979 华容道 题目描述 [问题描述] 小 B 最近迷上了华容道,可是他总是要花很长的时间才能完成一次.于是,他想到用编程来完成华容道:给定一种局面, 华容道是否根本就无法完成,如果能完成, 最少 ...

  9. 3537. 【NOIP2013提高组day2】华容道(搜索 + 剪枝)

    Problem 给出一个类似华容道的图.\(q\)次询问,每次给你起始点,终止点,空格位置,让你求最少步数 \(n,m\le 30, q\le 500\). Soultion 一道智障搜索题. 弱智想 ...

  10. NOIP2013提高组D2T3 华容道

    n<=30 * m<=30 的地图上,0表示墙壁,1表示可以放箱子的空地.q<=500次询问,每次问:当空地上唯一没有放箱子的空格子在(ex,ey)时,把位于(sx,sy)的箱子移动 ...

随机推荐

  1. python调用c++生成的dll

    前言 这个我查询了很多资料,所以到此为止,相当于做一个总结 c++代码如何生成dll #include<iostream> using namespace std; extern &quo ...

  2. 数电第三周周结_by_yc

    主要内容:Modelsim和Quartus的使用坑点 Modelsim: 新建Project:   在每新建一个verilog文件时,均需要添加一project的独立路径,否则不同文件之间会相互影响! ...

  3. 数据结构学习——BST删除特定节点

    BST删除特定节点 前言 一个平常的星期三晚上,一节通选课中,在老师放的视频和极寒空调的折磨之下,想着做点别的什么的我,打开了博客园.想起来做题下午数据结构课中老师最后在讲BST删除节点的操作,并且以 ...

  4. python + mysql +djagno +unittest 实现WEB、APP UI自动化测试平台--------(一)基础表

    from django.db import models # Create your models here. class DictConfig(models.Model): "" ...

  5. 【运维笔录】局域网实现项目的CI/CD,Docker+Gitea+Drone搭建轻量级自动化部署平台

    一.安装Docker 1.1 安装excpet $ apt-get -f install expect 1.2 编写执行Docker安装脚本 编写docker_dep.exp脚本 #!/usr/bin ...

  6. [OpenCV实战]4 OpenCV中的颜色空间

    目录 1 不同的色彩空间 1.1RGB颜色空间 1.2 Lab色彩空间 1.3  YCrCb颜色空间 1.4 HSV颜色空间 2 如何使用这些颜色空间进行分割 2.1 获取特定颜色的颜色值 2.2 应 ...

  7. RocketMQ Compaction Topic的设计与实现

    本文作者:刘涛,阿里云智能技术专家. 01 Compaction Topic介绍 一般来说,消息队列提供的数据过期机制有如下几种,比如有基于时间的过期机制--数据保存多长时间后即进行清理,也有基于数据 ...

  8. MongoDB6.0的安装「2023年」

    你好,我是悦创. 优质原文格式:https://bornforthis.cn/column/crawler/supplement/mongodb-install.html 点进去有惊喜. 吐槽,这篇博 ...

  9. Flutter异常监控 - 伍 | 关于异常监控框架设计的思考

    前言 最近阅读 Catcher.BugSnag.Rollbar 三个 Flutter 异常监控开源框架,文章链接如下: Flutter 异常监控 - 壹 | 从 Zone 说起 Flutter 异常监 ...

  10. 使用小黄鸟(HttpCanary)+模拟器(VMOS Pro)对手机APP进行抓包

    最近接触app开发,苦于app端不能像网页端可以F12看请求信息,对于后端来说当接口出现异常却不能拿到请求参数是很苦恼的, 因为之前了解过逍遥模拟器,先使用了模拟器对appj进行抓包,但发现这一款ap ...