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 }
  • 相关阅读:
    修复ecshop商品重量BUG小数位增至五位
    ECSHOP 支付宝发货确认接口,记录支付宝返回的交易号
    php数字补零的两种方法
    PHP获取当前时间的毫秒数(yyyyMMddHHmmssSSS)
    ajax 设置Access-Control-Allow-Origin实现跨域访问
    MySQL Master High Available 源码篇
    MHA 报错:There is no alive slave. We can't do failover
    cdid
    mha error
    mysql relay log参数汇总
  • 原文地址:https://www.cnblogs.com/xiefengze1/p/9776860.html
Copyright © 2011-2022 走看看