zoukankan      html  css  js  c++  java
  • [Luogu1979][NOIP2013]华容道(BFS+SPFA)

    考虑从起点到终点的过程,一定是先将空格子移到指定格子旁边,和指定格子交换,再移到下一个指定格子要到的地方,再交换,如此反复。

    于是问题分为两个部分:

    1.给定两个曼哈顿距离为2的格子求最短路,BFS即可。

    2.根据1的结果决定从起点到终点的路径,使用SPFA求解。

    其中,第一个问题空格子显然不能经过指定格子,BFS过程中需要特判。第二个问题的状态为(x,y,k),表示当前指定格子在(x,y),空格子在它的哪个方向(1<=k<=4)。

     1 #include<cstdio>
     2 #include<cstring>
     3 #include<algorithm>
     4 #define rep(i,l,r) for (int i=(l); i<=(r); i++)
     5 using namespace std;
     6 
     7 const int N=35,inf=1e9;
     8 const int dx[4]={-1,1,0,0},dy[4]={0,0,-1,1};
     9 bool inq[1<<14],mp[N][N];
    10 int n,m,Q,ex,ey,sx,sy,tx,ty,d[1<<14],dis[N][N],cost[1<<14];
    11 struct P{ int x,y; }q[1<<14];
    12 struct S{ int x,y,dir; }q2[1<<14];
    13 
    14 int F(int x,int y,int a,int b){ return x<<9 | y<<4 | a<<2 | b; }
    15 int F(int x,int y,int k){ return x<<7 | y<<2 | k; }
    16 
    17 void bfs(int x0,int y0,int x1,int y1){
    18     memset(dis,-1,sizeof(dis));
    19     mp[x1][y1]=0; int st=0,ed=1,tot=4; q[1]=(P){x0,y0}; dis[x0][y0]=0;
    20     while (st<ed){
    21         int x=q[++st].x,y=q[st].y;
    22         if (abs(x-x1)+abs(y-y1)==1)
    23             if (--tot==0) break;
    24         rep(k,0,3){
    25             int x2=x+dx[k],y2=y+dy[k];
    26             if (mp[x2][y2] && dis[x2][y2]==-1)
    27                 dis[x2][y2]=dis[x][y]+1,q[++ed]=(P){x2,y2};
    28         }
    29     }
    30     mp[x1][y1]=1;
    31 }
    32 
    33 void init(){
    34     rep(i,1,n) rep(j,1,m) if (mp[i][j])
    35         rep(p,0,3){
    36             int x1=i+dx[p],y1=j+dy[p];
    37             if (!mp[x1][y1]) continue;
    38             bfs(i,j,x1,y1);
    39             rep(q,0,3){
    40                 int x2=x1+dx[q],y2=y1+dy[q];
    41                 if (~dis[x2][y2]) cost[F(x1,y1,p^1,q)]=dis[x2][y2]+1;
    42             }
    43         }
    44 }
    45 
    46 int spfa(){
    47     int st=0,ed=0;
    48     memset(d,0x3f,sizeof(d));
    49     bfs(ex,ey,sx,sy);
    50     rep(k,0,3){
    51         int x1=sx+dx[k],y1=sy+dy[k];
    52         if (dis[x1][y1]==-1) continue;
    53         q2[++ed]=(S){sx,sy,k}; d[F(sx,sy,k)]=dis[x1][y1]; inq[F(sx,sy,k)]=1;
    54     }
    55     while (st<ed){
    56         int x=q2[++st].x,y=q2[st].y,dir=q2[st].dir,u=F(x,y,dir); inq[u]=0;
    57         rep(k,0,3){
    58             int x1=x+dx[k],y1=y+dy[k],c=cost[F(x,y,dir,k)],v=F(x1,y1,k^1);
    59             if (mp[x1][y1] && c && d[v]>d[u]+c){
    60                 d[v]=d[u]+c; if (!inq[v]) q2[++ed]=(S){x1,y1,k^1},inq[v]=1;
    61             }
    62         }
    63     }
    64     int ans=inf;
    65     rep(k,0,3) ans=min(ans,d[F(tx,ty,k)]);
    66     return ans==inf ? -1 : ans;
    67 }
    68 
    69 int main(){
    70     freopen("a.in","r",stdin);
    71     freopen("a.out","w",stdout);
    72     scanf("%d%d%d",&n,&m,&Q);
    73     rep(i,1,n) rep(j,1,m) scanf("%d",&mp[i][j]);
    74     init();
    75     while (Q--){
    76         scanf("%d%d%d%d%d%d",&ex,&ey,&sx,&sy,&tx,&ty);
    77         if (sx==tx && sy==ty) { puts("0"); continue; }
    78         printf("%d
    ",spfa());
    79     }
    80     return 0;
    81 }
  • 相关阅读:
    photoshop--图像大小(分辨率和宽高)
    Arduino--单向倾斜开关
    禁止google浏览器http链接强制跳转为https
    属性缓存_使用ConcurrentDictionary替代Hashtable对多线程的对象缓存处理
    .Net(windows服务器)清理缓存数据的几个方法
    【西天取经】(升级.net5)用了一整天才把项目从.netcoreapp3.1升级到.net5(转载)
    在Debian 9 vim中启用鼠标复制粘贴
    将数据批量插入SQL Server
    shell 脚本中 在grep -E '($wo|$ni|$ta)' 这里面用变量
    kubernetes 重启的几种方法
  • 原文地址:https://www.cnblogs.com/HocRiser/p/9837534.html
Copyright © 2011-2022 走看看