[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;
}
posted @ 2021-03-12 16:54  zjjws  阅读(162)  评论(0编辑  收藏  举报