zoukankan      html  css  js  c++  java
  • NOIP2013华容道(BFS+乱搞)

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

    Solution

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

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

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

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

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

    于是就不会了,滚去看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
    ");
                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
    ",ans);
            else printf("-1
    ");
        } 
        return 0;
    }
  • 相关阅读:
    Vasya and Endless Credits CodeForces
    Dreamoon and Strings CodeForces
    Online Meeting CodeForces
    数塔取数 基础dp
    1001 数组中和等于K的数对 1090 3个数和为0
    1091 线段的重叠
    51nod 最小周长
    走格子 51nod
    1289 大鱼吃小鱼
    POJ 1979 Red and Black
  • 原文地址:https://www.cnblogs.com/ZH-comld/p/9571371.html
Copyright © 2011-2022 走看看