• luogu1979 华容道 (dijkstra+bfs)


    我想动某个点的话,一定要先把空白点移动到这个点旁边,然后调换这个点和空白点,一直重复

    那么,我们就可以记一些状态(x,y,s) (s={0,1},{0,-1},{1,0},{-1,0}),表示我要动的点在(x,y),然后空白点在(x+s.x,y+s.y)

    这样的话我们就可以建图:$(x,y,s)-1->(x+s.x,y+s.y,s^{-1})$ (s^{-1}表示一个相反的方向,比如如果s是右边的话,那它就是左边)

    $(x,y,s)-C(x,y,s+s.x,y+s.y,x+i.x,y+i.y)->(x,y,i)$ 其中,C(a,b,c,d,e,f)表示我目前这个点在(a,b),空白点在(c,d),要把空白点挪到(e,f)的最小步数,而且挪的过程中不能经过(a,b)(要不然会把要动的那个点换走)

    这样的话,就可以一边bfs算出C的值,一边跑最短路了。

    然而复杂度$O(q*(mn)^2)$,过不去。

    考虑预处理出C,直接做显然不行($mn^3$),但其实我们要用到C的情况,都是空白点在要处理的点的旁边的,那它就可以压缩成(x,y,s,tx,ty),是900*4*900的。

    当然,一开始我们的空白点和要做的点并没有在一起,只要再单独bfs一下,先把空白点挪到它边上就可以了。

    要注意有起始点和目标点相同的情况,要判掉。

     1 #include<bits/stdc++.h>
     2 #define pa pair<int,int>
     3 #define pa2 pair<int,Node>
     4 #define ll long long
     5 using namespace std;
     6 const int maxn=33;
     7 
     8 inline ll rd(){
     9     ll x=0;char c=getchar();int neg=1;
    10     while(c<'0'||c>'9'){if(c=='-') neg=-1;c=getchar();}
    11     while(c>='0'&&c<='9') x=x*10+c-'0',c=getchar();
    12     return x*neg;
    13 }
    14 
    15 struct Node{
    16     int x,y,s;
    17     Node (int x1,int x2,int x3){x=x1,y=x2,s=x3;}
    18 };
    19 int f[maxn][maxn],N,M,Q,dis[maxn][maxn][4][maxn][maxn],dis2[maxn][maxn][4];
    20 int step[4][2]={{0,1},{0,-1},{1,0},{-1,0}};
    21 bool can[maxn][maxn],flag[maxn][maxn],flag2[maxn][maxn][4];
    22 queue<pa > q;
    23 priority_queue<pa2,vector<pa2>,greater<pa2> > q2;
    24 
    25 bool operator < (Node a,Node b){return a.x<b.x;}
    26 
    27 int bfs1(int a,int b,int c,int x0,int y0){
    28     memset(flag,0,sizeof(flag));
    29     while(!q.empty()) q.pop();q.push(make_pair(x0,y0));
    30     dis[a][b][c][x0][y0]=0;
    31     while(!q.empty()){
    32         int x=q.front().first,y=q.front().second;q.pop();
    33         for(int i=0;i<=3;i++){
    34             int xx=x+step[i][0],yy=y+step[i][1];
    35             if(!flag[xx][yy]&&can[xx][yy]){
    36                 q.push(make_pair(xx,yy));
    37                 dis[a][b][c][xx][yy]=dis[a][b][c][x][y]+1;
    38             }
    39         }flag[x][y]=1;
    40     }
    41 }
    42 
    43 int dijkstra(int ex,int ey,int sx,int sy,int tx,int ty){
    44     if(sx==tx&&sy==ty) return 0;
    45     memset(dis2,-1,sizeof(dis2));memset(flag2,0,sizeof(flag2));
    46     while(!q2.empty()) q2.pop();
    47     can[sx][sy]=0;memset(dis[0][0][0],-1,sizeof(dis[0][0][0]));
    48     bfs1(0,0,0,ex,ey);
    49     for(int i=0;i<=3;i++){
    50         int xx=sx+step[i][0],yy=sy+step[i][1];
    51         if(dis[0][0][0][xx][yy]!=-1){
    52             dis2[xx][yy][i^1]=dis[0][0][0][xx][yy]+1;
    53             q2.push(make_pair(dis2[xx][yy][i^1],Node(xx,yy,i^1)));
    54         }
    55     }can[sx][sy]=1;
    56     while(!q2.empty()){
    57         Node p=q2.top().second;q2.pop();if(flag2[p.x][p.y][p.s]) continue;
    58         for(int i=0;i<=3;i++){
    59             int xx=p.x+step[i][0],yy=p.y+step[i][1];
    60             if(dis[p.x][p.y][p.s][xx][yy]!=-1){
    61                 if(dis2[xx][yy][i^1]==-1||dis2[xx][yy][i^1]>dis[p.x][p.y][p.s][xx][yy]+dis2[p.x][p.y][p.s]+1){
    62                     dis2[xx][yy][i^1]=dis[p.x][p.y][p.s][xx][yy]+dis2[p.x][p.y][p.s]+1;
    63                     q2.push(make_pair(dis2[xx][yy][i^1],Node(xx,yy,i^1)));
    64                 }
    65             }
    66         }flag2[p.x][p.y][p.s]=1;
    67     }int re=-1;
    68     for(int i=0;i<=3;i++){
    69         if(dis2[tx][ty][i]==-1) continue;
    70         if(re==-1) re=dis2[tx][ty][i];
    71         else re=min(re,dis2[tx][ty][i]);
    72     }return re;
    73 }
    74 
    75 int main(){
    76     int i,j,k;
    77     N=rd(),M=rd();Q=rd();
    78     for(i=1;i<=N;i++){
    79         for(j=1;j<=M;j++) can[i][j]=rd();
    80     }
    81     memset(dis,-1,sizeof(dis));
    82     for(i=1;i<=N;i++){
    83         for(j=1;j<=M;j++){
    84             if(!can[i][j]) continue;can[i][j]=0;
    85             for(k=0;k<=3;k++){
    86                 int ii=i+step[k][0],jj=j+step[k][1];
    87                 if(can[ii][jj]) bfs1(i,j,k,ii,jj);
    88             }can[i][j]=1;
    89         }
    90     }
    91     for(i=1;i<=Q;i++){
    92         int x1=rd(),x2=rd(),x3=rd(),x4=rd(),x5=rd(),x6=rd();
    93         printf("%d
    ",dijkstra(x1,x2,x3,x4,x5,x6));
    94     }
    95     return 0;
    96 }
  • 相关阅读:
    rhel 6.4 + udev+ 11.2.0.3 + gi + asm+ rac 双节点安装
    rhel 6.4 + udev + 11.2.0.3 + asm 单点安装
    vmware 中linux虚拟机动态添加硬盘
    flashback drop
    flashback query
    11g crsctl start/stop crs 和 crsctl start/stop cluster 的关系
    10g crs 启动报错的记录
    检测数据库日志的切换频率及归档文件大小的sql
    用widthStep的方法来增加某范围的像素----与imageROI对比
    用imageROI来增加某范围的像素
  • 原文地址:https://www.cnblogs.com/Ressed/p/9636099.html
Copyright © 2020-2023  润新知