[NOIP2013 提高组] 华容道

题链


Solution

移动的策略非常显然,将白格移至特殊格的上下左右的其中一个位置,然后交换两者。不停重复这个过程即可。

会发现我们可以把特殊格的位置,以及白格在其上下左右的四种可能,看做状态。那么状态的转移,一共只有 n242 种,这个东西与单次询问无关,可以预处理。

这个预处理暴力一点 dfs 或者 bfs 都是可以的。

至于之后搜索的过程,实际上是 SPFA 和 Dji 都是可以的。不过我第一发 SPFA T 掉了,我没想多就写了比较恶心的 Dji 写法。

事实上 Dji 也会 T,原因是我开了 O2。

关了 O2 就跑得飞快。


Code

非常阳间的代码(

#include <vector> #include <stdio.h> #include <string.h> #define LL long long using namespace std; const int Rea=1e5+3; struct Rin { char c; inline char gc() { static char rea[Rea]; static char *head,*tail; return head==tail&&(tail=(head=rea)+fread(rea,1,Rea,stdin),head==tail)?EOF:*head++; } inline Rin&operator >>(int &x) { x=0; bool tag=false; for(c=gc();c>'9'||c<'0';c=gc())if(c=='-'){c=gc();tag=true;break;} for(;c>='0'&&c<='9';c=gc())x=(x<<1)+(x<<3)+(c^'0'); if(tag)x=-x; return *this; } }rin; inline int abs(int x){return (x<0)?(-x):(x);} inline void jh(int &x,int &y){if(x^y)x^=y^=x^=y;return;} const int N=31; int n,m; int a[N][N]; int b[N][N]; int f[4][4][N][N]; int xt[4]={0,0,1,-1}; int yt[4]={1,-1,0,0}; vector<pair<int,int> >d; inline void bfs(int X,int Y,int Z,bool tag) { memset(b,0x3f,sizeof(b));b[X][Y]=0;d.clear();d.push_back(make_pair(X,Y)); for(int i=0;i<d.size();i++) { X=d[i].first;Y=d[i].second; for(int j=0;j<4;j++) { int x=X+xt[j],y=Y+yt[j]; if(a[x][y]||b[x][y]!=0x3f3f3f3f)continue; d.push_back(make_pair(x,y));b[x][y]=b[X][Y]+1; } } if(tag)return; X=d.front().first+xt[Z];Y=d.front().second+yt[Z]; for(int i=0;i<4;i++)f[Z][i][d.front().first][d.front().second]=b[X+xt[i]][Y+yt[i]]; return; } inline void init() { for(int i=1;i<=n;i++)for(int j=1;j<=m;j++)rin>>a[i][j],a[i][j]=1-a[i][j]; for(int i=1;i<=n;i++)a[i][0]=a[i][m+1]=1; for(int i=1;i<=m;i++)a[0][i]=a[n+1][i]=1; for(int i=1;i<=n;i++) { for(int j=1;j<=m;j++) { if(a[i][j])continue; for(int k=0;k<4;k++) { if(a[i+xt[k]][j+yt[k]])continue; a[i+xt[k]][j+yt[k]]=1;bfs(i,j,k,0);a[i+xt[k]][j+yt[k]]=0; } } } return; } pair<int,int>w,S,T; int g[4][N][N]; bool tag[4][N][N]; inline int XP(pair<int,pair<int,int> >x){return ((x.second.first-1)*m+x.second.second-1)*4+x.first+1;} inline pair<int,pair<int,int> > PX(int x){return make_pair((x-1)%4,make_pair(((x-1)/4)/m+1,((x-1)/4)%m+1));} struct gyq { int d[N*N<<2]; int val[N*N<<2]; int num[N*N<<2]; int tail; inline void jh_(int &x,int &y){jh(d[x],d[y]);jh(x,y);return;} inline void up(int x){if(x==1||!tail)return;if(val[d[x]]<val[d[x>>1]])jh_(num[d[x]],num[d[x>>1]]),up(x>>1);return;} inline void down(int x) { if((x<<1)>tail)return; int nxt=x;if(val[d[x<<1]]<val[d[nxt]])nxt=x<<1;if(((x<<1)|1)<=tail&&val[d[(x<<1)|1]]<val[d[nxt]])nxt=(x<<1)|1; if(nxt!=x)jh_(num[d[x]],num[d[nxt]]),down(nxt);return; } inline void change(int num_,int val_){val[num_]=val_;down(num[num_]);up(num[num_]);return;} inline void push(int num_,int val_){d[++tail]=num_;num[num_]=tail;val[num_]=val_;up(tail);return;} inline void push_back(pair<int,pair<int,int> >x){push(XP(x),g[x.first][x.second.first][x.second.second]);return;} inline void pop(){jh_(num[d[1]],num[d[tail]]);tail--;down(1);return;} inline bool empty(){return tail==0;} inline void clear(){tail=0;return;} inline pair<int,pair<int,int> >top(){return PX(d[1]);} }D; inline void work() { memset(g,0x3f,sizeof(g));D.clear(); rin>>w.first>>w.second>>S.first>>S.second>>T.first>>T.second;if(S==T){puts("0");return;} a[S.first][S.second]=1;bfs(w.first,w.second,0,1);a[S.first][S.second]=0; int X=S.first,Y=S.second,Z,ans=0x3f3f3f3f; for(int i=0;i<4;i++)if((g[i][X][Y]=b[X+xt[i]][Y+yt[i]])!=0x3f3f3f3f)D.push_back(make_pair(i,make_pair(X,Y))),tag[i][X][Y]=true; for(;!D.empty();) { pair<int,pair<int,int> >now=D.top();D.pop(); X=now.second.first;Y=now.second.second;Z=now.first;tag[Z][X][Y]=false; if(X+xt[Z]==T.first&&Y+yt[Z]==T.second){ans=min(ans,g[Z][X][Y]+1);continue;} for(int j=0;j<4;j++) { if(a[X+xt[Z]+xt[j]][Y+yt[Z]+yt[j]])continue; if(g[j][X+xt[Z]][Y+yt[Z]]>g[Z][X][Y]+f[Z][j][X][Y]+1) { g[j][X+xt[Z]][Y+yt[Z]]=g[Z][X][Y]+f[Z][j][X][Y]+1; if(!tag[j][X+xt[Z]][Y+yt[Z]])D.push_back(make_pair(j,make_pair(X+xt[Z],Y+yt[Z]))),tag[j][X+xt[Z]][Y+yt[Z]]=true; else D.change(XP(make_pair(j,make_pair(X+xt[Z],Y+yt[Z]))),g[j][X+xt[Z]][Y+yt[Z]]); } } } if(ans==0x3f3f3f3f)ans=-1;printf("%d\n",ans); return; } int main() { int q;rin>>n>>m>>q;init();for(;q;q--)work();return 0; }

__EOF__

本文作者zjjws
本文链接https://www.cnblogs.com/zjjws/p/14524946.html
关于博主:我就是:究极的 Mad Scientist,凤—凰—院—凶—真da!
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:这么屑的博主有什么声援的必要吗?
posted @   zjjws  阅读(169)  评论(0编辑  收藏  举报
编辑推荐:
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
阅读排行:
· winform 绘制太阳,地球,月球 运作规律
· AI与.NET技术实操系列(五):向量存储与相似性搜索在 .NET 中的实现
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)
点击右上角即可分享
微信分享提示