zoukankan      html  css  js  c++  java
  • 【NOIP2013】 华容道 bfs预处理+bfs

    这一题我们考虑一个最裸的算法:

    我们设$dp[i][j][k][l]$表示当前棋子在$(i,j)$且空格在$(k,l)$时的最小步数

    然后显然随便转移一下就好了,时间复杂度为$O(q(nm)^2)$。可以获得$80$分的好成绩(我自测的时候只打了这个)

    我们发现这一题有一些很优秀的性质:

    首先整个图是静态的,且起点,终点,出现空格的位置均非障碍物。

    那么对于这个性质,我们做一些微小的预处理。

    考虑到当空格与目标棋子四相邻的时候,棋子才能往空格内移动。那么整个走棋的过程可以理解为:调整空格位置-移动棋子到空格里-调整空格位置

    我们设$f[i][j][k][l]$表示在不经过$(i,j)$的情况下,将空格从$(i+wx[k],j+wy[k])$移动到$(i+wx[l],j+wy[l])$的最小步数,其中$wx,wy$满足$|wx[i]+wy[i]|=1$,显然有四种组合。

    对于每一个$f[i][j][k][l]$,我们通过一次$bfs$去求解。

    预处理$f$的时间复杂度显然为$O(16nm)$。

    下面考虑每一组询问:

    若起点和终点的坐标相同,那么显然输出$0$就好了。

    若起点和终点坐标不相同,我们先考虑将空格移动到起点四相邻的位置,所需要的最小步数显然可以通过一次$bfs$求得。

    然后我们设$d[i][j][k]$表示当前棋子在$(i,j)$时,空格在$(i+wx[k],j+wy[k])$的最小步数。

    显然随便$bfs$就可以进行更新了。最后的答案显然是$min(d[tx][ty][])$。

    时间复杂度$O(16nm+4qnm)$。跑得飞快。

      1 #include<bits/stdc++.h>
      2 #define M 32
      3 #define INF 16843009
      4 using namespace std;
      5 int n,m,q,mp[M][M]={0},dis[M][M]={0},d[M][M][4]={0},f[M][M][4][4]={0};
      6 const int wx[]={0,1,0,-1};
      7 const int wy[]={1,0,-1,0};
      8 queue<int> qx,qy,qk;
      9 void bfs(int X,int Y){
     10     memset(dis,1,sizeof(dis));
     11     qx.push(X); qy.push(Y); dis[X][Y]=0;
     12     while(!qx.empty()){
     13         X=qx.front(); qx.pop();
     14         Y=qy.front(); qy.pop();
     15         for(int i=0;i<4;i++){
     16             int _x=X+wx[i],_y=Y+wy[i];
     17             if(mp[_x][_y]&&dis[_x][_y]>dis[X][Y]+1){
     18                 dis[_x][_y]=dis[X][Y]+1;
     19                 qx.push(_x); qy.push(_y);
     20             }
     21         }
     22     }
     23 }
     24 void move(int x,int y){
     25     memset(dis,1,sizeof(dis));
     26     qx.push(x); qy.push(y); dis[x][y]=0;
     27     while(!qx.empty()){
     28         x=qx.front(); qx.pop();
     29         y=qy.front(); qy.pop();
     30         for(int i=0;i<4;i++){
     31             int _x=x+wx[i],_y=y+wy[i];
     32             if(mp[_x][_y]&&dis[_x][_y]>dis[x][y]+1){
     33                 dis[_x][_y]=dis[x][y]+1;
     34                 qx.push(_x); qy.push(_y);
     35             }
     36         }
     37     }
     38 }
     39 
     40 
     41 void bfs(){
     42     while(!qx.empty()){
     43         int x=qx.front(); qx.pop();
     44         int y=qy.front(); qy.pop();
     45         int k=qk.front(); qk.pop();
     46         for(int i=0;i<4;i++){
     47             int _x=x+wx[i],_y=y+wy[i];
     48             if(mp[_x][_y]==0) continue;
     49             if(d[_x][_y][(i+2)&3]>d[x][y][k]+f[x][y][k][i]+1){
     50                 d[_x][_y][(i+2)&3]=d[x][y][k]+f[x][y][k][i]+1;
     51                 qx.push(_x); qy.push(_y); qk.push((i+2)&3);
     52             }
     53         }
     54     }
     55 }
     56             
     57 int main(){
     58     scanf("%d%d%d",&n,&m,&q);
     59     for(int i=1;i<=n;i++)
     60     for(int j=1;j<=m;j++) scanf("%d",&mp[i][j]);
     61     
     62     for(int i=1;i<=n;i++)
     63     for(int j=1;j<=m;j++)
     64     if(mp[i][j]){
     65         mp[i][j]=0;
     66         for(int k=0;k<4;k++)
     67         if(mp[i+wx[k]][j+wy[k]]){
     68             bfs(i+wx[k],j+wy[k]);
     69             for(int l=0;l<4;l++)
     70             f[i][j][k][l]=dis[i+wx[l]][j+wy[l]];
     71         }
     72         mp[i][j]=1;
     73     }
     74     
     75     while(q--){
     76         int ex,ey,sx,sy,tx,ty;
     77         cin>>ex>>ey>>sx>>sy>>tx>>ty;
     78         if(sx==tx&&sy==ty){
     79             printf("0
    ");
     80             continue;
     81         }
     82         mp[sx][sy]=0;
     83         move(ex,ey);
     84         mp[sx][sy]=1;
     85         memset(d,1,sizeof(d));
     86         for(int i=0;i<4;i++)
     87         if(mp[sx+wx[i]][sy+wy[i]]){
     88             qx.push(sx);
     89             qy.push(sy);
     90             qk.push(i);
     91             d[sx][sy][i]=dis[sx+wx[i]][sy+wy[i]];
     92         }
     93         bfs();
     94         int minn=INF;
     95         for(int i=0;i<4;i++)
     96         minn=min(minn,d[tx][ty][i]);
     97         if(minn==INF) printf("-1
    ");
     98         else cout<<minn<<endl;
     99     }
    100 }
  • 相关阅读:
    python 的基础 学习 第六天 基础数据类型的操作方法 字典
    python 的基础 学习 第五天 基础数据类型的操作方法
    python 的基础 学习 第四天 基础数据类型
    ASP.NET MVC 入门8、ModelState与数据验证
    ASP.NET MVC 入门7、Hellper与数据的提交与绑定
    ASP.NET MVC 入门6、TempData
    ASP.NET MVC 入门5、View与ViewData
    ASP.NET MVC 入门4、Controller与Action
    ASP.NET MVC 入门3、Routing
    ASP.NET MVC 入门2、项目的目录结构与核心的DLL
  • 原文地址:https://www.cnblogs.com/xiefengze1/p/9776860.html
Copyright © 2011-2022 走看看