NOIP2013华容道(BFS+乱搞)

n<=30 * m<=30 的地图上,0表示墙壁,1表示可以放箱子的空地。q<=500次询问,每次问:当空地上唯一没有放箱子的空格子在(ex,ey)时,把位于(sx,sy)的箱子移动到(tx,ty)的最小步数。

Solution

一开始听说这道题很难,所以刚拿到题就开始打暴力,emmm。。。

比较native的思路是记录当前点的位置和空白点的位置,然后暴力转移。

但这个状态十分没有必要,因为我的位置能动的前提是空格在我的当前位置的旁边。

所以我们把状态变成当前点的位置和空白点在当前点的什么方位。

但转移变得困难了,因为我还需要知道从一个点到另一个点不经过某个点的最短距离。

于是就不会了,滚去看TJ。

发现不能经过的点就在当前点的旁边。

所以我们n^2*m^2*4的预处理出这个东西。

但初始状态怎么搞?不能经过的点不在起点旁边啊?

考虑暴力处理这个问题。

发现能过2333

注意判0的情况。

Code

#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
#include<cstdlib>
#include<cmath>
#define R register
#define mm make_pair
using namespace std;
const int dx[4]={0,0,-1,1};
const int dy[4]={1,-1,0,0};
struct node{
    int x,y,tag;
};
queue<node>q;
queue<pair<int,int> >que; 
int a[32][32],ex,ey,sx,sy,tx,ty,n,m,qu,dis[32][32][4],ans,mi[32][32][4][32][32],ji[5],di[32][32];
bool vis[32][32][4],visi[32][32];
inline int rd(){
    int x=0;char c=getchar();while(!isdigit(c))c=getchar();
    while(isdigit(c)){x=(x<<1)+(x<<3)+(c^48);c=getchar();}
    return x;
}
inline void BFS(int ii,int jj,int x2,int y2,int tag){
    que.push(mm(ii,jj));
    mi[ii][jj][tag][ii][jj]=0;
    while(!que.empty()){
        int u1=que.front().first,u2=que.front().second;visi[u1][u2]=0;que.pop();
        for(int i=0;i<4;++i){
            int v1=u1+dx[i],v2=u2+dy[i];
            if((v1==x2&&v2==y2)||!a[v1][v2])continue;
            if(mi[ii][jj][tag][v1][v2]>mi[ii][jj][tag][u1][u2]+1){
                mi[ii][jj][tag][v1][v2]=mi[ii][jj][tag][u1][u2]+1;
                if(!visi[v1][v2]){
                    visi[v1][v2]=1;
                    que.push(mm(v1,v2));
                }
            }
        }
    }
}
inline void BB(int ii,int jj,int x2,int y2){
    que.push(mm(ii,jj));
    memset(di,0x3f,sizeof(di));
    di[ii][jj]=0;
    while(!que.empty()){
        int u1=que.front().first,u2=que.front().second;visi[u1][u2]=0;que.pop();
        for(int i=0;i<4;++i){
            int v1=u1+dx[i],v2=u2+dy[i];
            if((v1==x2&&v2==y2)||!a[v1][v2])continue;
            if(di[v1][v2]>di[u1][u2]+1){
                di[v1][v2]=di[u1][u2]+1;
                if(!visi[v1][v2]){
                    visi[v1][v2]=1;
                    que.push(mm(v1,v2));
                }
            }
        }
    }
}
int main(){
    n=rd();m=rd();qu=rd();ji[0]=1;ji[3]=2;ji[1]=0;ji[2]=3;
    memset(mi,0x3f,sizeof(mi));
    for(R int i=1;i<=n;++i)for(R int j=1;j<=m;++j)a[i][j]=rd();
    for(R int i=1;i<=n;++i)
      for(R int j=1;j<=m;++j)
        for(R int k=0;k<4;++k)BFS(i,j,i+dx[k],j+dy[k],k);
    while(qu--){
        ex=rd();ey=rd();sx=rd();sy=rd();tx=rd();ty=rd();
        if(tx==sx&&ty==sy){
            printf("0\n");
            continue;
        }
        memset(dis,0x3f,sizeof(dis));
        for(int i=0;i<4;++i){
            int xx=sx+dx[i],yy=sy+dy[i];
            BB(ex,ey,sx,sy);
            if(di[xx][yy]!=0x3f3f3f3f){
            q.push(node{sx,sy,i});
            dis[sx][sy][i]=di[xx][yy];
             }
        }
        ans=0x7f7f7f7f;
        while(!q.empty()){
            node u=q.front();q.pop();vis[u.x][u.y][u.tag]=0;
            if(u.x==tx&&u.y==ty){
                ans=min(ans,dis[u.x][u.y][u.tag]);
                continue;
            }
            for(R int i=0;i<4;++i){
                R int xx=u.x+dx[i],yy=u.y+dy[i];
                if(!a[xx][yy])continue;
                int x=u.x+dx[u.tag],y=u.y+dy[u.tag],z=mi[x][y][ji[u.tag]][xx][yy]+1;
                if(dis[xx][yy][ji[i]]>dis[u.x][u.y][u.tag]+z){
                    dis[xx][yy][ji[i]]=dis[u.x][u.y][u.tag]+z;
                    if(!vis[xx][yy][ji[i]]){
                        vis[xx][yy][ji[i]]=1;
                        q.push(node{xx,yy,ji[i]});
                    }
                }
            }
        }
        if(ans!=0x7f7f7f7f)printf("%d\n",ans);
        else printf("-1\n");
    } 
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/ZH-comld/p/9571371.html