Escape along Water Pipe(2021牛客暑期多校训练营1)
分析:BFS。由于管的型号已知,所以只要记录 x ,y 和进入该点的方向即可。
7.27_upd:从上进入是0,从左是1,从下2,从右3.这个type数组是用来计算转动角度的,比如type[0][2]意思是上一个格子从上进入,这一个格子从下进入。你会发现4*4种情况每一种情况都和一种管子一一对应(这里面的“-1”是不合法情况),然后type[0][1] 是管子1,假如map【x】【y】对应的是管子2,那么他们做差就是转过的角度。
代码:
#include <cstdio>
#include <algorithm>
#include <cmath>
#include <map>
#include <cstring>
#include <queue>
#include <vector>
#include <iostream>
#define LL long long
#define LD long double
#define MAXN 1005
#define MAXM
#define P
#define MP make_pair
#define PB push_back
#define INF 0x3f3f3f3f
#define dbg(a...) fprintf(stderr, a)
using namespace std;
int T, n, m, mp[MAXN][MAXN], vis[MAXN][MAXN][4];
const int dx[4]={1, 0, -1, 0};
const int dy[4]={0, 1, 0, -1};
const int type[4][4]={
{5, 1, -1, 0},
{3, 4, 0, -1},
{-1, 2, 5, 3},
{2, -1, 1, 4}
};
struct Sta {int x, y, dir;} pre[MAXN][MAXN][4];
bool check(int x, int y, int dir)
{
if(x==n+1 && y==m && dir==0) return true;
if(x<1 || x>n || y<1 || y>m || vis[x][y][dir]) return false;
return true;
}
void print(Sta sta, int step)
{
int x=sta.x, y=sta.y, dir=sta.dir;
if(x==1 && y==1 && dir==0) {
printf("%d\n", step*2);
return;
}
Sta psta=pre[x][y][dir];
print(psta, step+1);
int px=psta.x, py=psta.y, pdir=psta.dir;
int tmp=type[pdir][dir];
if(tmp<4)
printf("1 %d %d %d\n", (tmp-mp[px][py]+4)%4*90, px, py);
else
printf("1 %d %d %d\n", (tmp-mp[px][py]+2)%2*90, px, py);
mp[px][py]=tmp;
printf("0 %d %d\n", px, py);
}
bool bfs()
{
queue<Sta> q;
q.push(Sta{1, 1, 0});
vis[1][1][0]=1;
while(!q.empty()) {
int x=q.front().x, y=q.front().y, dir=q.front().dir;
q.pop();
if(mp[x][y]<4) {
int ndir=(dir+1)%4;
int nx=x+dx[ndir], ny=y+dy[ndir];
if(check(nx, ny, ndir)) {
q.push(Sta{nx, ny, ndir});
vis[nx][ny][ndir]=1;
pre[nx][ny][ndir]=Sta{x, y, dir};
}
ndir=(dir+3)%4;
nx=x+dx[ndir], ny=y+dy[ndir];
if(check(nx, ny, ndir)) {
q.push(Sta{nx, ny, ndir});
vis[nx][ny][ndir]=1;
pre[nx][ny][ndir]=Sta{x, y, dir};
}
if(nx==n+1 && ny==m && ndir==0) return true;
} else {
int ndir=dir;
int nx=x+dx[ndir], ny=y+dy[ndir];
if(check(nx, ny, ndir)) {
q.push(Sta{nx, ny, ndir});
vis[nx][ny][ndir]=1;
pre[nx][ny][ndir]=Sta{x, y, dir};
}
if(nx==n+1 && ny==m && ndir==0) return true;
}
}
return false;
}
int main()
{
scanf("%d", &T);
while(T--) {
scanf("%d%d", &n, &m);
for(int i=1; i<=n; ++i)
for(int j=1; j<=m; ++j) {
scanf("%d", &mp[i][j]);
memset(vis[i][j], 0, sizeof(vis[i][j]));
}
if(bfs()) {
printf("YES\n");
print(Sta{n+1, m, 0}, 0);
} else {
printf("NO\n");
}
}
return 0;
}
/*
1
4 3
5 2 1
5 5 2
4 5 4
2 0 3
*/