连连看

http://acm.hdu.edu.cn/showproblem.php?pid=1175

与普通的BFS不同的是这里的vis数组不是标记是否被访问过,而是记录到这个点的最小转弯次数。

#include<stdio.h>
#include<string.h>
#include<queue>
#include<algorithm>
using namespace std;

const int INF = 0x3f3f3f3f;
int grid[1100][1100];
int vis[1100][1100];
int dire[5][2] = {{0,0},{1,0},{0,-1},{-1,0},{0,1}};
struct node
{
	int x,y;
	int dir;//到达这点的方向,规定向下为1,向左为2,向上为3,向右为4.
	int turn;//转弯次数
};
int n,m;

int BFS(int x1, int y1, int x2, int y2)
{
	if(grid[x1][y1] == 0 || grid[x2][y2] == 0)
		return 0;
	if(grid[x1][y1] != grid[x2][y2])
		return 0;

	queue<struct node> que;
	while(!que.empty())
		que.pop();
	que.push((struct node){x1,y1,-1,0});//起点进队列,方向为-1,转弯次数为0.

	while(!que.empty())
	{
		struct node u = que.front();
		que.pop();

		if(u.x == x2 && u.y == y2)
			return 1;

		for(int i = 1; i <= 4; i++)
		{
			int xx = u.x+dire[i][0];
			int yy = u.y+dire[i][1];
			if(xx >= 1 && xx <= n && yy >= 1 && yy <= m && (grid[xx][yy] == 0 ||(xx == x2 && yy == y2)))
			{
				if(u.dir == -1)
				{
					que.push((struct node){xx,yy,i,0});
					vis[xx][yy] = 0;
				}
				else if(u.dir == i && vis[xx][yy] >= u.turn)
				{
					que.push((struct node){xx,yy,i,u.turn});
					vis[xx][yy] = u.turn;
				}
				else
				{
					if(u.turn < 2 && vis[xx][yy] >= u.turn+1)
					{
						que.push((struct node){xx,yy,i,u.turn+1});
						vis[xx][yy] = u.turn+1;
					}
				}
			}
		}
	}
	return 0;
}

int main()
{
	while(~scanf("%d %d",&n,&m) && (n || m))
	{
		for(int i = 1; i <= n; i++)
		{
			for(int j = 1; j <= m; j++)
				scanf("%d",&grid[i][j]);
		}

		int q,x1,y1,x2,y2;
		scanf("%d",&q);
		while(q--)
		{
			memset(vis,INF,sizeof(vis));
			scanf("%d %d %d %d",&x1,&y1,&x2,&y2);
			if(x1 < 1 || x2 < 1 || x1 > n || x2 > n || y1 < 1 || y2 < 1 || y2 > m || y1 > m)
			{
				printf("NO\n");
				continue;
			}
			if(BFS(x1,y1,x2,y2))
				printf("YES\n");
			else printf("NO\n");
		}
	}
	return 0;
}


你可能感兴趣的:(搜索)