感觉和以前做过的一个推箱子很像,都是可以用bfs解决的,而且都是手玩出结论。

因为起始棋子肯定是要和空格交换的,所以第一件事是先把空格移到棋子旁边。然后讨论怎么设计搜索状态。由于和推箱子实在太像了,所以直接借鉴,发现空格总是要贴着棋子走的要不然就是换个贴的方向继续走(这里的走就是指交换)。于是绑定两者,设计状态$f_{i,j,dir}$表示在棋子在某个格子,空格在上下左右四方位时候的最小移动次数。显然可以暴力bfs跑,但是这样没有经过优化,效率不高,实际上只要把它改的像最短路算法一点就行了,比如套个dijkstra,把每种状态和他可以推到的下一步状态(分为交换,或者空格跑到另一侧,这个的步数可以提前预处理)之间连边,边权即步数,这样建个图之后就是最短路了,起点有4个,终点有4个,$O(Qn^2\text{log}n^2)$,避免了bfs庞大的搜索树。

然后注意一个很容易忽略的细节。。我第一发就是这么挂掉的。。起点和终点在同一个位置要特判,不然会加上空格到起点的距离然后跪好多点。

code可能是我有史以来写过的最丑的,一堆循环展开。

 #include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<queue>
#define dbg(x) cerr << #x << " = " << x <<endl
using namespace std;
typedef long long ll;
typedef double db;
typedef pair<int,int> pii;
template<typename T>inline T _min(T A,T B){return A<B?A:B;}
template<typename T>inline T _max(T A,T B){return A>B?A:B;}
template<typename T>inline char MIN(T&A,T B){return A>B?(A=B,):;}
template<typename T>inline char MAX(T&A,T B){return A<B?(A=B,):;}
template<typename T>inline void _swap(T&A,T&B){A^=B^=A^=B;}
template<typename T>inline T read(T&x){
x=;int f=;char c;while(!isdigit(c=getchar()))if(c=='-')f=;
while(isdigit(c))x=x*+(c&),c=getchar();return f?x=-x:x;
}
const int N=+,INF=0x3f3f3f3f;
int mp[N][N],f[N][N][][],id[N][N][],cnt;
int n,m,Q,hx,hy,sx,sy,tx,ty;
int qx[],qy[],dis[N][N],l,r;
inline void bfs_step(int x,int y){
memset(dis,0x3f,sizeof dis);qx[l=r=]=x,qy[]=y,dis[x][y]=;
while(l<=r){
int i=qx[l],j=qy[l++];
if(!mp[i-][j]&&MIN(dis[i-][j],dis[i][j]+))qx[++r]=i-,qy[r]=j;
if(!mp[i+][j]&&MIN(dis[i+][j],dis[i][j]+))qx[++r]=i+,qy[r]=j;
if(!mp[i][j-]&&MIN(dis[i][j-],dis[i][j]+))qx[++r]=i,qy[r]=j-;
if(!mp[i][j+]&&MIN(dis[i][j+],dis[i][j]+))qx[++r]=i,qy[r]=j+;
}
}
struct thxorz{int to,nxt,w;}G[];
int Head[],tot;
inline void Addedge(int x,int y,int z){
G[++tot].to=y,G[tot].nxt=Head[x],Head[x]=tot,G[tot].w=z;
G[++tot].to=x,G[tot].nxt=Head[y],Head[y]=tot,G[tot].w=z;
}
int dist[];
priority_queue<pii,vector<pii>,greater<pii> > q;
#define y G[j].to
inline void dij(int xx,int yy){
memset(dist,0x3f,sizeof dist);
if(id[xx][yy][])q.push(make_pair(dist[id[xx][yy][]]=dis[xx-][yy],id[xx][yy][]));
if(id[xx][yy][])q.push(make_pair(dist[id[xx][yy][]]=dis[xx][yy+],id[xx][yy][]));
if(id[xx][yy][])q.push(make_pair(dist[id[xx][yy][]]=dis[xx+][yy],id[xx][yy][]));
if(id[xx][yy][])q.push(make_pair(dist[id[xx][yy][]]=dis[xx][yy-],id[xx][yy][]));
while(!q.empty()){
int x=q.top().second,d=q.top().first;q.pop();
if(dist[x]^d)continue;
for(register int j=Head[x];j;j=G[j].nxt)if(MIN(dist[y],d+G[j].w))q.push(make_pair(dist[y],y));
}
}
#undef y
int main(){//freopen("test.in","r",stdin);freopen("test.ans","w",stdout);
read(n),read(m),read(Q);memset(mp,0x3f,sizeof mp);
for(register int i=;i<=n;++i)for(register int j=;j<=m;++j)read(mp[i][j]),mp[i][j]^=;
for(register int i=;i<=n;++i)for(register int j=;j<=m;++j)if(!mp[i][j]){
mp[i][j]=;
if(!mp[i-][j])bfs_step(i-,j),f[i][j][][]=dis[i][j+],f[i][j][][]=dis[i+][j],f[i][j][][]=dis[i][j-],id[i][j][]=++cnt;
if(!mp[i][j+])bfs_step(i,j+),f[i][j][][]=dis[i-][j],f[i][j][][]=dis[i+][j],f[i][j][][]=dis[i][j-],id[i][j][]=++cnt;
if(!mp[i+][j])bfs_step(i+,j),f[i][j][][]=dis[i-][j],f[i][j][][]=dis[i][j+],f[i][j][][]=dis[i][j-],id[i][j][]=++cnt;
if(!mp[i][j-])bfs_step(i,j-),f[i][j][][]=dis[i-][j],f[i][j][][]=dis[i][j+],f[i][j][][]=dis[i+][j],id[i][j][]=++cnt;
mp[i][j]=;
}
for(register int i=;i<=n;++i)for(register int j=;j<=m;++j)if(!mp[i][j]){
for(register int thx=;thx<;++thx)for(register int orz=;orz<;++orz)
if(orz^thx&&id[i][j][thx]&&id[i][j][orz])Addedge(id[i][j][thx],id[i][j][orz],f[i][j][thx][orz]);
if(id[i][j][])Addedge(id[i][j][],id[i-][j][],);
if(id[i][j][])Addedge(id[i][j][],id[i][j-][],);
}
while(Q--){
read(hx),read(hy),read(sx),read(sy),read(tx),read(ty);
if(sx==tx&&sy==ty){puts("");continue;}
mp[sx][sy]=;bfs_step(hx,hy);mp[sx][sy]=;
dij(sx,sy);
int tmp=_min(dist[id[tx][ty][]],_min(dist[id[tx][ty][]],_min(dist[id[tx][ty][]],dist[id[tx][ty][]])));
printf("%d\n",tmp<INF?tmp:-);
}
return ;
}

总结:棋盘类问题求最小解有常用方法就是最短路建模,注意考虑状态设计有效性,必要时跑分层图。

loj2613 「NOIP2013」华容道[最短路]的更多相关文章

  1. 「NOIP2013」华容道

    传送门 Luogu 解题思路 预支一点东西: 这题其实有着更为思维的图模型,还十分考验码力,不简单啊 这居然是联赛题 讲正解: 显然我们对于一种合法方案,空格子肯定是一直围绕着特定棋子反复横跳的. 所 ...

  2. 「NOIP2013」「LuoguP1967」货车运输(最大生成树 倍增 LCA

    题目描述 AA国有nn座城市,编号从 11到nn,城市之间有 mm 条双向道路.每一条道路对车辆都有重量限制,简称限重.现在有 qq 辆货车在运输货物, 司机们想知道每辆车在不超过车辆限重的情况下,最 ...

  3. LG1983 「NOIP2013」车站分级 拓扑排序

    问题描述 LG1983 题解 考虑建立有向边\((a,b)\),代表\(a\)比\(b\)低级. 于是枚举每一辆车次经过的车站\(x \in [l,r]\),如果不是车辆停靠的车站,则从\(x\)向每 ...

  4. 「NOIP2013」货车运输

    传送门 Luogu 解题思路 首先 \(\text{Kruskal}\) 一下,构造出一棵森林. 并查集还要用来判断连通性. 倍增 \(\text{LCA}\) 的时候顺便维护一下路径最小值即可. 细 ...

  5. 「bzoj1003」「ZJOI2006」物流运输 最短路+区间dp

    「bzoj1003」「ZJOI2006」物流运输---------------------------------------------------------------------------- ...

  6. 2090. 「ZJOI2016」旅行者 分治,最短路

    2090. 「ZJOI2016」旅行者 链接 loj 思路 \((l,mid)(mid+1,r)\).考虑跨过mid的贡献. 假设选的中间那条线的点为gzy,贡献为\(dis(x,gzy)+dis(g ...

  7. 「BZOJ3694」「FJ2014集训」最短路

    「BZOJ3694」「FJ2014集训」最短路 首先树剖没得说了,这里说一下并查集的做法, 对于一条非树边,它会影响的点就只有u(i),v(i)到lca,对于lca-v的路径上所有点x,都可通过1-t ...

  8. 「luogu4366」最短路

    「luogu4366」最短路 传送门 直接连边显然不行,考虑优化. 根据异或的结合律和交换律等优秀性质,我们每次只让当前点向只有一位之别的另一个点连边,然后就直接跑最短路. 注意点数会很多,所以用配对 ...

  9. 「ZJOI2016」解题报告

    「ZJOI2016」解题报告 我大浙的省选题真是超级神仙--这套已经算是比较可做的了. 「ZJOI2016」旅行者 神仙分治题. 对于一个矩形,每次我们从最长边切开,最短边不会超过 \(\sqrt{n ...

随机推荐

  1. 9.centos7 安装mysql

    sudo yum install libaio # 安装依赖包 检查 MySQL 是否已安装 sudo yum list installed | grep mysql 也可以通过命令 rpm -qa| ...

  2. 神奇的负margin解决border“合并”

    如上图所示,这是一个分页样式,a:hover时,需要改变边框的颜色. 我们知道,除表格之外,其他标签的border是不能合并的.要解决这个问题,思路有三: 1.table布局(大概很少有人愿意在这里使 ...

  3. 线性基求交(2019牛客国庆集训派对day4)

    题意:https://ac.nowcoder.com/acm/contest/1109/C 问你有几个x满足A,B集合都能XOR出x. 思路: 就是线性基求交后,有几个基就是2^几次方. #defin ...

  4. 如何使用加多宝(jdb)在linux下调试Java程序

    毕业时写了一段时间的C,那时候调试使用gdb,后来转了java,当时就想java程序怎么调试,找了一下,果然,那就是jdk自带的jdb windows里是这样的 Linux下是这样的 一般我在linu ...

  5. java----FileInputStream类与FileReader类的区别(转)

    FileInputStream类与FileReader类的区别:两个类的构造函数的形式和参数都是相同的,参数为File对象或者表示路径的String,它们到底有何区别呢? Readers and W ...

  6. Left4Dead2 LAN Online

    Left4Dead2 LAN Online Franklin vs Wolverine 求生之路 局域网联机说明 ============================ 局域网联机方法: 1.先找到 ...

  7. 客户端相关知识学习(八)之Android“.9.png”

    参考 Android中.9图片的含义及制作教程 .9.png Android .9.png 的介绍

  8. 将java文件编译成class文件

    一般情况下,在myeclipse中保存java文件后会自动编译成class文件,但是这种情况只能编译当前工程的java文件,但是如果需要编译不是一个工程的java文件,比如在网上拷贝的java文件改如 ...

  9. iframe标签(页面嵌套)

    本文链接:https://blog.csdn.net/weixin_44540236/article/details/92760494 两个不同的页面但是它们的基本框架都是一样,每点击一次左边的导航栏 ...

  10. Linux下的打包操作

    范例一:将整个 test 目录下的文件全部打包成为 test.tar[python@master ~]$ tar -cvf test.tar test/         ==仅打包,不压缩!test/ ...