Nowcodercontest5278 K 迷宫
cnblogs界面
可以说看起来不难写起来真的不简单,还得封装一下
:
定义表示当前位置,是否用过传送,枚举转移,用就能满足转移顺序
:
可以看到有三种转移形式
对于的两种状态之间用转移
的状态转移
这三种转移形式我们把它们分开三部分,对于的转移,每次取到的区域是一个矩形
定义辅助数组表示第行,范围在范围内的的最小值和出现位置
固定,然后从小到大枚举,是一个标准的单调队列模板
然后固定,从小到大枚举,找到最小的即可
#include<cstdio> #include<cctype> #include<queue> #include<cstring> #include<iostream> #include<algorithm> #include<set> #include<cmath> #include<cassert> using namespace std; #define reg register typedef long long ll; #define rep(i,a,b) for(reg int i=a,i##end=b;i<=i##end;++i) #define drep(i,a,b) for(reg int i=a,i##end=b;i>=i##end;--i) #define pb push_back template <class T> inline void cmin(T &a,T b){ ((a>b)&&(a=b)); } template <class T> inline void cmax(T &a,T b){ ((a<b)&&(a=b)); } char IO; template<class T=int> T rd(){ T s=0; int f=0; while(!isdigit(IO=getchar())) if(IO=='-') f=1; do s=(s<<1)+(s<<3)+(IO^'0'); while(isdigit(IO=getchar())); return f?-s:s; } const int N=2e3+10,INF=1e9+10; int n,m,d,sx,sy,fx,fy; char s[N][N]; pair <int,int> pre1[N][N],pre2[N][N],pre3[N][N]; // 记录了转移方案 int dis[N][N]; queue <pair <int,int> > que; // bfs序列 const int z[5][4]={{-1,0},{1,0},{0,1},{0,-1}}; struct Node{ int x,y,d; bool operator < (const Node __) const { return d<__.d; } bool operator > (const Node __) const { return d>__.d; } }A[N][N<<1],B[N*N]; //x,y决策位置,d为决策权值 int cnt; Node Q[N]; int L,R; int ansx[N*N*2],ansy[N*N*2],ansc; int main(){ n=rd(),m=rd(),d=rd(); rep(i,1,n) scanf("%s",s[i]+1); rep(i,1,n) rep(j,1,m) if(s[i][j]=='S') sx=i,sy=j; rep(i,1,n) rep(j,1,m) if(s[i][j]=='T') fx=i,fy=j; //三步转移 //Part1 rep(i,1,n) rep(j,1,m) dis[i][j]=INF; que.push(make_pair(sx,sy)),dis[sx][sy]=0; while(!que.empty()) { int x=que.front().first,y=que.front().second; que.pop(); rep(i,0,3) { int x1=x+z[i][0],y1=y+z[i][1]; if(dis[x1][y1]==INF && s[x1][y1]!='X') dis[x1][y1]=dis[x][y]+1,pre1[x1][y1]=make_pair(x,y),que.push(make_pair(x1,y1)); } } //Part2 rep(i,1,n) { L=1,R=0; rep(j,1,m+d) { while(L<=R && Q[L].y<j-d*2) ++L; if(dis[i][j]<INF && j<=m) { Node t=(Node){i,j,dis[i][j]}; while(L<=R && Q[R]>t) --R; Q[++R]=t; } if(L<=R) A[i][j]=Q[L]; } } rep(j,1,m) { int ry=j+d,now=0; L=1,R=0; rep(i,1,n) { int lx=max(1,i-d),rx=min(n,i+d); while(L<=R && Q[L].x<lx) ++L; while(now<rx) { ++now; if(!A[now][ry].x) continue while(L<=R && Q[R]>A[now][ry]) R--; Q[++R]=A[now][ry]; } if(s[i][j]!='X' && L<=R && Q[L].x && Q[L].d+1<dis[i][j]) dis[i][j]=Q[L].d+1,pre2[i][j]=make_pair(Q[L].x,Q[L].y); } } //Part3 rep(i,1,n) rep(j,1,m) B[++cnt]=(Node){i,j,dis[i][j]}; sort(B+1,B+cnt+1); rep(i,1,cnt) que.push(make_pair(B[i].x,B[i].y)); while(!que.empty()) { int x=que.front().first,y=que.front().second; que.pop(); rep(i,0,3) { int x1=x+z[i][0],y1=y+z[i][1]; if(dis[x1][y1]>dis[x][y]+1 && s[x1][y1]!='X') dis[x1][y1]=dis[x][y]+1,pre3[x1][y1]=make_pair(x,y),que.push(make_pair(x1,y1)); } } //输出方案 if(dis[fx][fy]==INF) return puts("-1"),0; int x=fx,y=fy; ansx[++ansc]=x,ansy[ansc]=y; while(pre3[x][y].first) { auto t=pre3[x][y]; x=t.first,y=t.second; ansx[++ansc]=x,ansy[ansc]=y; } if(pre2[x][y].first) { auto t=pre2[x][y]; x=t.first,y=t.second; ansx[++ansc]=x,ansy[ansc]=y; } while(pre1[x][y].first) { auto t=pre1[x][y]; x=t.first,y=t.second; ansx[++ansc]=x,ansy[ansc]=y; } printf("%d\n",ansc-1); drep(i,ansc,1) printf("%d %d\n",ansx[i]-1,ansy[i]-1); }