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
*/

posted @ 2021-07-19 09:27  GUO_dx  阅读(120)  评论(3编辑  收藏  举报