[NOIP2013 提高组] 华容道
Solution
移动的策略非常显然,将白格移至特殊格的上下左右的其中一个位置,然后交换两者。不停重复这个过程即可。
会发现我们可以把特殊格的位置,以及白格在其上下左右的四种可能,看做状态。那么状态的转移,一共只有 \(n^2\cdot 4^2\) 种,这个东西与单次询问无关,可以预处理。
这个预处理暴力一点 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;
}
$$\texttt{Dirty Deeds Done Dirt Cheap}$$