2021牛客多校第一场 E——Escape along Water Pipe

这篇博客介绍了如何使用BFS(广度优先搜索)解决一个与赛尔号游戏类似的图中管道旋转问题。题目要求从起点到终点,通过旋转每个管道使其能连接起来。博主提供了详细的解题思路,包括模拟BFS过程,记录每个节点的进入方向,以及计算相邻节点之间的旋转角度。代码实现中,定义了坐标、方向和转动角度的数组,并通过一个队列进行BFS遍历。最后,博主给出了输出路径及旋转角度的方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目大意

在这里插入图片描述
在这里插入图片描述
给你一个这样的图,你可以旋转每一块,从起点到终点(玩过赛尔号的都懂)

解题思路

模拟 B F S BFS BFS,记录一下进入的方向和坐标即可
t y p e type type 数组
从上进入是0,从左是1,从下2,从右3.这个 t y p e type type 数组是用来计算转动角度的,比如 t y p e [ 0 ] [ 2 ] type[0][2] type[0][2]意思是上一个格子从上进入,这一个格子从下进入。你会发现 4 ∗ 4 4*4 44种情况每一种情况都和一种管子一一对应(这里面的“-1”是不合法情况),然后 t y p e [ 0 ] [ 1 ] type[0][1] type[0][1] 是管子1,假如 m a p [ x ] [ y ] map[x][y] map[x][y]对应的是管子2,那么他们做差就是转过的角度

Code

#include <bits/stdc++.h>
#define ll long long
#define qc ios::sync_with_stdio(false); cin.tie(0);cout.tie(0)
#define fi first
#define se second
#define PII pair<int, int>
#define PLL pair<ll, ll>
#define pb push_back
using namespace std;
const int MAXN = 1007;
const int inf = 0x3f3f3f3f;
const ll INF = 0x3f3f3f3f3f3f3f3f;
const ll mod = 1e9 + 7;
inline int read()
{
    int x=0,f=1;char ch=getchar();
    while (!isdigit(ch)){if (ch=='-') f=-1;ch=getchar();}
    while (isdigit(ch)){x=x*10+ch-48;ch=getchar();}
    return x*f;
}
int n, m;
// 0上 1左 2下 3右
int xx[4] = {1, 0, -1, 0};
int yy[4] = {0, 1, 0, -1};
int type[4][4] = {
	{5, 1, -1, 0},
	{3, 4, 0, -1},
	{-1, 2, 5, 3},
	{2, -1, 1, 4}
};

struct node{
	int x, y, dir;
}pre[MAXN][MAXN][4];
int mp[MAXN][MAXN];
int vis[MAXN][MAXN][4];

bool check(int x, int y, int d){
	if(x == n+1 && y == m && d == 0)
		return 1;
	if(x < 1 || x > n || y < 1 || y > m || vis[x][y][d])
		return 0;
	return 1;
}
void print(node nd, int st){
	int x = nd.x, y = nd.y, d = nd.dir;
	if(x == 1 && y == 1 && !d){
		cout << st*2 << endl;
		return;
	}
	node pr = pre[x][y][d];
	print(pr, st+1);
	int px = pr.x, py = pr.y, pd = pr.dir;
	int tmp = type[pd][d];
	if(tmp < 4){
		cout << "1 " << (tmp - mp[px][py] + 4) % 4 * 90
		<< " " << px << " " << py << endl;
	}
	else
		cout << "1 " << (tmp - mp[px][py] + 2) % 2 * 90
		<< " " << px << " " << py << endl;
	mp[px][py] = tmp;
	cout << "0 " << px << " " << py << endl;
}
int bfs(){
	queue<node> q;
	q.push(node{1, 1, 0});
	vis[1][1][0] = 1;
	while(!q.empty()){
		node tmp = q.front();
		q.pop();
		int x = tmp.x;
		int y = tmp.y;
		int d = tmp.dir;
		if(mp[x][y] < 4){
			int nd = (d + 1) % 4;
			int nx = x + xx[nd];
			int ny = y + yy[nd];
			if(check(nx, ny, nd)){
				q.push(node{nx, ny, nd});
				vis[nx][ny][nd] = 1;
				pre[nx][ny][nd] = node{x, y, d};
			}
			nd = (d + 3) % 4;
			nx = x + xx[nd];
			ny = y + yy[nd];
			if(check(nx, ny, nd)){
				q.push(node{nx, ny, nd});
				vis[nx][ny][nd] = 1;
				pre[nx][ny][nd] = node{x, y, d};
			}
			if(nx == n+1 && ny == m && nd == 0)
				return 1;
		}
		else{
			int nd = d;
			int nx = x + xx[nd];
			int ny = y + yy[nd];
			if(check(nx, ny, nd)){
				q.push(node{nx, ny, nd});
				vis[nx][ny][nd] = 1;
				pre[nx][ny][nd] = node{x, y, d};
			}
			if(nx == n+1 && ny == m && nd == 0)
				return 1;
		}
	}
	return 0;
}
void solve(){
    cin >> n >> m;
    for(int i = 1; i <= n; i++)
    	for(int j = 1; j <= m; j++){
    		memset(vis[i][j], 0, sizeof(vis[i][j]));
    		cin >> mp[i][j];
    	}
    if(bfs()){
    	cout << "YES\n";
    	print(node{n+1, m, 0}, 0);
    }
    else
    	cout << "NO\n";

}
int main()
{
	#ifdef ONLINE_JUDGE
    #else
       freopen("in.txt", "r", stdin);
       freopen("out.txt", "w", stdout);
    #endif

	qc;
    int T;
    cin >> T;
    // T = 1;
    while(T--){

        solve();
    }
	return 0;
}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值