分析

一个比较显然的方式是

设 \(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. 解决python3解压文件名乱码问题(unzip)

    看来很多文章,不过我觉得最有效的还是改源码,因为我用的sublime text 3有插件Anaconda可以很方便的跳转到源码文件,你也可以入python3 的安装目录, 搜索 zipfile.py这 ...

  2. <七>理解多态

    理解多态 多种多样的形态(静态多态,动态多态) 静态多态(编译时期) 1:函数重载 bool comparet(int ,int); bool compare(double,double); comp ...

  3. Google Chrome(谷歌浏览器)安装使用

    谷歌浏览器官网https://www.google.cn/chrome/ Chrome是由Google开发的一款简单便捷的网页浏览工具.谷歌浏览器(Google Chrome)可以提帮助你快速.安全的 ...

  4. 4.11:Storm之WordCount

    〇.概述 1.拓扑结构 2.目标 使用storm进行计数实验. 一.启动服务   在网页中输入:http://localhost:8081可以查看storm的相关信息. 二.kafka操作 终端中输入 ...

  5. 【大数据面试】【框架】Hive:架构、计算引擎、比较、内外部表、by、函数、优化、数据倾斜、动静态分区

    一.组成 1.架构 源数据原本是存在dubby数据库,存在MySQL可以支持多个客户端 客户端.数据存储(HDFS).MR计算引擎 2.计算引擎的选择 MR引擎:基于磁盘,计算时间长,但一定能算出结果 ...

  6. <七>lambda表达式实现原理

    C++11 函数对象的升级版=>lambda表达式 函数对象的缺点: 使用在泛型算法,参数传递, 比较性质/自定义操作 优先级队列, 需要专门定义出一个类 //lambda表达式语法: //[捕 ...

  7. Java工厂模式的最佳实践?

    "Simplicity is prerequisite for reliability." - Edsger Dijkstra "简单是可靠的前提条件." -- ...

  8. 为什么 Random.Shared 是线程安全的

    在多线程环境中使用 Random 类来生成伪随机数时,很容易出现线程安全问题.例如,当多个线程同时调用 Next 方法时,可能会出现种子被意外修改的情况,导致生成的伪随机数不符合预期. 为了避免这种情 ...

  9. 前后端开发必会的 HTTP 协议“十全大补丸”(万字长文)

    本文全面介绍了 HTTP 协议相关知识,包括 HTTP 请求报文.响应报文.持久连接.缓存.Cookie 以及 HTTP 版本升级等! HTTP 协议全称为 HyperText Transfer Pr ...

  10. nacos注册中心单节点ap架构源码解析

    一.注册流程 单nacos节点流程图如下: 流程图可以知,Nacos注册流程包括客户端的服务注册.服务实例列表拉取.定时心跳任务:以及服务端的定时检查服务实例任务.服务实例更新推送5个功能. 服务注册 ...