HOJ 1175 连连看(bfs)

23 篇文章 0 订阅

bfs
本题要点:
1、连连看,先保证起点和终点,都不是0,且相等。
2、然后从起点 s 开始bfs, 用 step 记录拐弯次数。拐弯不超过两次。
3、direction 表示,进入点 (x, y) ,是从哪个方向进来的。
比如某一点 (x, y), 它的 direction == 0, 表示 (x, y)的上一点 是 从 左右方向进入 (x, y)。
此时,点(x, y) 的下一点,只需要从上下方向寻找。
4、点(x, y) 沿着上方向,一直走,直到不能走为止。所谓不能走,就是说,遇到非空白的地方。
当遇到 终点 t,表示可以找到一条路径(拐弯次数不超过2次), 从s到t。
代码较长,其中四个方向都是类似的代码。

#include <cstdio>
#include <cstring>
#include <iostream>
#include <queue>
using namespace std;
const int MaxN = 1010;
int n, m, query;
int mp[MaxN][MaxN];
bool vis[MaxN][MaxN];

struct node
{
	int x, y, step;
	int direction;	//direction 表示,进入点 (x, y) ,是从哪个方向进来的
};					// direction == 0, 表示从 左右方向; direction == 0 表示从上下方向。 direction == -1, 表示点(x, y) 是起点
node s, t;

bool judge(int x, int y)
{
	return x >= 1 && x <= n && y >= 1 && y <= m;
}

void bfs()
{
	for(int i = 0; i <= n; ++i)
		for(int j = 0; j <= m; ++j)
			vis[i][j] = false;
	int ax, ay;
	node tmp;
	s.step = -1, s.direction = -1;
	queue<node> q;
	q.push(s);
	vis[s.x][s.y] = true;
	while(q.size())
	{
		node now = q.front();q.pop();
		ax = now.x, ay = now.y;	
		if(now.step >= 2)	continue;
		if(now.direction == -1 || now.direction == 1)// 往左,右
		{
			ax = now.x, ay = now.y;	
			while(true) // 往左
			{
				if(judge(ax, ay - 1) == false)	break;
				if(!(ax == t.x && ay - 1 == t.y) && mp[ax][ay - 1] == 0)
				{
					if(vis[ax][ay - 1] == false)	
					{
						vis[ax][ay - 1] = true;
						tmp.x = ax, tmp.y = ay - 1, tmp.direction = 0, tmp.step = now.step + 1;
						q.push(tmp);
					}
				}else{
					if(ax == t.x && ay - 1 == t.y)
					{
						printf("YES\n");
						return;
					}
					break;
				}
				--ay;
			}
			ax = now.x, ay = now.y;	
			while(true)
			{
				if(judge(ax, ay + 1) == false)	break;
				if(!(ax == t.x && ay + 1 == t.y) && mp[ax][ay + 1] == 0)
				{
					if(vis[ax][ay + 1] == false)	
					{
						vis[ax][ay + 1] = true;
						tmp.x = ax, tmp.y = ay + 1, tmp.direction = 0, tmp.step = now.step + 1;
						q.push(tmp);
					}
				}else{
					if(ax == t.x && ay + 1 == t.y)
					{
						printf("YES\n");
						return;
					}
					break;
				}
				++ay;
			}
		}
		//往上,下
		if(now.direction == -1 || now.direction == 0)
		{
			ax = now.x, ay = now.y;	
			while(true)	// 上
			{
				if(judge(ax - 1, ay) == false)  break;
				if(!(ax - 1 == t.x && ay == t.y) && mp[ax - 1][ay] == 0)
				{
					if(vis[ax - 1][ay] == false)
					{
						vis[ax - 1][ay] = true;
						tmp.x = ax - 1, tmp.y = ay, tmp.direction = 1, tmp.step = now.step + 1;
						q.push(tmp);
					}
				}else{
					if(ax - 1 == t.x && ay == t.y)
					{
						printf("YES\n");
						return;
					}
					break;
				}
				--ax;
			}
			ax = now.x, ay = now.y;	
			while(true)	// 下
			{
				if(judge(ax + 1, ay) == false)  break;
				if(!(ax + 1 == t.x && ay == t.y) && mp[ax + 1][ay] == 0)
				{
					if(vis[ax + 1][ay] == false)
					{
						vis[ax + 1][ay] = true;
						tmp.x = ax + 1, tmp.y = ay, tmp.direction = 1, tmp.step = now.step + 1;
						q.push(tmp);
					}
				}else{
					if(ax + 1 == t.x && ay == t.y)
					{
						printf("YES\n");
						return;
					}
					break;
				}
				++ax;
			}
		}
	}
	printf("NO\n");
}

int main()
{
	while(scanf("%d%d", &n, &m) != EOF)
	{
		if(0 == n && 0 == m)	break;
		for(int i = 1; i <= n; ++i)
		{
			for(int j = 1; j <= m; ++j)
			{
				scanf("%d", &mp[i][j]);
			}
		}
		scanf("%d", &query);
		for(int i = 0; i < query; ++i)
		{
			scanf("%d%d%d%d", &s.x, &s.y, &t.x, &t.y);
			if(mp[s.x][s.y] == 0 || mp[t.x][t.y] == 0 || (mp[s.x][s.y] != mp[t.x][t.y]))
			{
				printf("NO\n");
			}else
				bfs();
		}
	}
	return 0;
}

/*
3 4
1 2 3 4
0 0 0 0
4 3 2 1
4
1 1 3 4
1 1 2 4
1 1 3 3
2 1 2 4
3 4
0 1 4 3
0 2 4 1
0 0 0 0
2
1 1 2 4
1 3 2 3
0 0
*/

/*
YES
NO
NO
NO
NO
YES
*/
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值