• BFS 华容道


    这里写图片描述
    这里写图片描述
    整体思路是BFS没问题,但对于500个询问还是很吃力。但又因为只有一张图,所以我们可以预处理一些东西。
    那么来看,对于要移动的点,无非是把空格移动到他的四周,之后交换位置,而交换位置之前有大量无用的转移,而这个转移的耗费对于某个点是确定不变的,而致有转移起点才是有效的,起点与空格交换位置后,空格依然在起点的周围,那么就可以预处理出对于每一个点,他不移动的情况下,若空格在他周围(上下左右)某个位置时,移动到他周围另一个位置的耗费。
    而对于主函数,首先处理出空格到起点四周的耗费(因为空格不在起点附近)之后进行spfa,有两个转移。
    1,空格从这个点的周围某一位置转移到周围另一个位置,
    2,此点与他周围某个位置上的空格交换位置。
    细节蛮多的,但推荐自己打。

    #include<cstdio>
    #include<cstdlib>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    #include<queue>
    #define ll long long
    #define mod 1000000007
    using namespace std;
    int n,m,Q,a[35][35],l[35][35][5][5],d[35][35][5],vis[35][35][5];
    int v[35][35],dis[35][35],wz[5][2]={0,0,-1,0,0,1,1,0,0,-1},hhh[5],hh[5]={0,3,4,1,2};
    struct zb
    {
        int x,y;
        zb(){}
        zb(int x_,int y_){x=x_;y=y_;}
    }S,T,kg;
    struct dp
    {
        int x,y,z;
        dp(){}
        dp(int x_,int y_,int z_){x=x_;y=y_;z=z_;}
    };
    queue<zb> q;
    queue<dp> qq;
    void bfs(int x,int y)
    {
         memset(dis,30,sizeof(dis));
         dis[x][y]=0;v[x][y]=1;
         q.push(zb(x,y));
         while(!q.empty())
         {
             zb k=q.front();
             for(int i=1;i<=4;i++)
             {
                 zb to;to.x=k.x+wz[i][0],to.y=k.y+wz[i][1];
                 if(!a[to.x][to.y]||to.x>n||to.x<1||to.y>m||to.y<1)continue;
                 if(dis[to.x][to.y]>dis[k.x][k.y]+1)
                 {
                      dis[to.x][to.y]=dis[k.x][k.y]+1;
                      if(!v[to.x][to.y])
                      {
                          v[to.x][to.y]=1;
                          q.push(to);
                      }
                 }
             }
             q.pop();v[k.x][k.y]=0;
         }
    }
    void init()
    {
         for(int i=1;i<=n;i++)
           for(int j=1;j<=m;j++)
           {
               if(!a[i][j])continue;
               for(int k=1;k<=4;k++)
               {
                   a[i][j]=0;
                   int x=i+wz[k][0],y=j+wz[k][1];
                   //if(x>n||x<1||y>m||y<1)continue;
                   bfs(x,y);
                   for(int h=1;h<=4;h++)
                      if(h!=k)
                         l[i][j][k][h]=dis[i+wz[h][0]][j+wz[h][1]];
                   a[i][j]=1;
               }
           }
    }
    void spfa()
    {
         memset(d,30,sizeof(d));
         for(int i=1;i<=4;i++)
         {
             int x=S.x+wz[i][0],y=S.y+wz[i][1];
             if(!a[x][y]||x<1||x>n||y<1||y>m)continue;
             d[S.x][S.y][i]=hhh[i];vis[S.x][S.y][i]=1;
             qq.push(dp(S.x,S.y,i));
         }
         while(!qq.empty())
         {
              dp k=qq.front();qq.pop();vis[k.x][k.y][k.z]=0;
              int x=k.x+wz[k.z][0],y=k.y+wz[k.z][1];
              if(a[x][y]&&x<=n&&x>=1&&y<=m&&y>=1)
              {
                  if(d[x][y][hh[k.z]]>d[k.x][k.y][k.z]+1)
                  {
                       d[x][y][hh[k.z]]=d[k.x][k.y][k.z]+1;
                       if(!vis[x][y][hh[k.z]])
                       {
                           vis[x][y][hh[k.z]]=1;
                           qq.push(dp(x,y,hh[k.z]));
                       }
                  }
              }
              for(int j=1;j<=4;j++)
              {
                  if(j==k.z||!a[k.x+wz[j][0]][k.y+wz[j][1]])continue;
                  dp to;to.x=k.x+wz[j][0];to.y=k.y+wz[j][1],to.z=j;
                  if(d[k.x][k.y][j]>d[k.x][k.y][k.z]+l[k.x][k.y][k.z][j])
                  {
                       d[k.x][k.y][j]=d[k.x][k.y][k.z]+l[k.x][k.y][k.z][j];
                       if(!vis[k.x][k.y][j])
                       {
                           vis[k.x][k.y][j]=1;
                           qq.push(dp(k.x,k.y,j));
                       }
                  }
              }
         }
    }
    int main()
    {
        //freopen("PuzzleNOIP2013.in","r",stdin);
        //freopen("PuzzleNOIP2013.out","w",stdout);
        cin>>n>>m>>Q;
        for(int i=1;i<=n;i++)
           for(int j=1;j<=m;j++)
              scanf("%d",&a[i][j]);
        init();
        while(Q--)
        {
            scanf("%d%d%d%d%d%d",&kg.x,&kg.y,&S.x,&S.y,&T.x,&T.y);
            if(S.x==T.x&&S.y==T.y){printf("0
    ");continue;}  
            a[S.x][S.y]=0;
            bfs(kg.x,kg.y);
            a[S.x][S.y]=1;
            for(int i=1;i<=4;i++)hhh[i]=dis[S.x+wz[i][0]][S.y+wz[i][1]];
            spfa();
            int ans=100000000;
                for(int i=1;i<=4;i++)ans=min(ans,d[T.x+wz[i][0]][T.y+wz[i][1]][hh[i]]+1);
            if(ans==100000000)printf("-1
    ");
            else printf("%d
    ",ans);    
        }
    }
  • 相关阅读:
    access数据库
    备份
    本机测试三级域名
    xp共享
    An error occurred on the server when processing the URL解决方法
    GridView导出Excel研究
    SQL触发器实例讲解1
    谈不上喜悦,算得上疲劳作战
    架构讨论
    梦——软件问题最终用硬件方式解决——跳出思维怪圈(原创)
  • 原文地址:https://www.cnblogs.com/QTY2001/p/7632692.html
Copyright © 2020-2023  润新知