noip2013华容道--搜索题

链接:https://www.luogu.org/problemnew/show/P1979

一眼就能看出是搜索,但如果暴力广搜的话搜一次状态有(n^2*m^2),q=500会tle,那么要考虑减少状态数量,发现华容道这东西想要移动当前棋子必须把空白格移到当前位置四个方位之一上,那么就可以预处理了,状态数变为n*m*4个,但这时不能跑bfs要跑最短路,上个狄杰斯特拉或者spfa就行。

// luogu-judger-enable-o2
#include<bits/stdc++.h>
using namespace std;
const int dx[]={-1,1,0,0};
const int dy[]={0,0,-1,1};
int n,m,q,mp[35][35],gt[35][35][35][35][4];//0 up 1 dw 2 left 3 right
bool vis[35][35];
int ex,ey,sx,sy,tx,ty,dis[35][35][4];
struct in{
    int x,y,d;
    in(){x=0,y=0,d=0;}
    in(int xx,int yy,int dd):x(xx),y(yy),d(dd){}
};
struct gg{
    int x,y,op,d;
    gg(){x=0,y=0,op=0,d=0;}
    gg(int xx,int yy,int pp,int dd):x(xx),y(yy),op(pp),d(dd){}
    friend bool operator <(const gg a,const gg b)
    {return a.d>b.d;}
};
void init_bfs(int bgx,int bgy,int opt)
{
    in nw;int nx,ny;
    static queue<in>q;
    memset(vis,0,sizeof vis);
    nw=in(bgx,bgy,0);
    nw.x+=dx[opt],nw.y+=dy[opt];
    if(mp[nw.x][nw.y]==1)q.push(nw);
    while(!q.empty())
    {
        nw=q.front(),q.pop();
        if(nw.x==bgx&&nw.y==bgy)continue;
        gt[bgx][bgy][nw.x][nw.y][opt]=nw.d;
        vis[nw.x][nw.y]=1;
        for(int i=0;i<4;i++)
        {
            nx=nw.x+dx[i],ny=nw.y+dy[i];
            if(nx>=1&&nx<=n&&ny>=1&&ny<=m&&!vis[nx][ny]&&mp[nx][ny]==1)
                q.push(in(nx,ny,nw.d+1));
        }
    }
}
int dij()
{
    if(sx==tx&&sy==ty)return 0;
    gg nw,nx;int x,y,xx,yy,d,ans=2e9;
    static priority_queue<gg>q;
    memset(dis,127,sizeof dis);
    for(int i=0;i<4;i++)
        if(gt[sx][sy][ex][ey][i]!=-1)q.push(gg(sx,sy,i,dis[sx][sy][i]=gt[sx][sy][ex][ey][i]));
    while(!q.empty())
    {
        nw=q.top(),q.pop();
        x=nw.x,y=nw.y,xx=x+dx[nw.op],yy=y+dy[nw.op],d=nw.d;
        if(x==tx&&y==ty){ans=min(ans,d);continue;}
        if(d!=dis[x][y][nw.op])continue;
        swap(x,xx),swap(y,yy),d++;
        if(x==tx&&y==ty){ans=min(ans,d);continue;}
        for(int i=0;i<4;i++)
        {
            if(gt[x][y][xx][yy][i]!=-1)
            {
                if(dis[x][y][i]>d+gt[x][y][xx][yy][i])
                {
                    dis[x][y][i]=d+gt[x][y][xx][yy][i];
                    q.push(gg(x,y,i,dis[x][y][i]));
                }
            }
        }
    }
    if(ans>=1e9)ans=-1;
    return ans;
}
int main()
{
    scanf("%d%d%d",&n,&m,&q);
    for(int i=1;i<=n;i++)
    {
        for(int j=1;j<=m;j++)
        {
            scanf("%d",&mp[i][j]);
        }
    }
    memset(gt,-1,sizeof gt);
    for(int i=1;i<=n;i++)
    {
        for(int j=1;j<=m;j++)
        {
            init_bfs(i,j,0);
            init_bfs(i,j,1);
            init_bfs(i,j,2);
            init_bfs(i,j,3);
        }
    }
    for(int i=1;i<=q;i++)
        scanf("%d%d%d%d%d%d",&ex,&ey,&sx,&sy,&tx,&ty),printf("%d\n",dij());
}

猜你喜欢

转载自blog.csdn.net/caoyang1123/article/details/81586646
今日推荐