HDU-1175 连连看 BFS

连连看

Time Limit: 20000/10000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 5613    Accepted Submission(s): 1455


Problem Description

“连 连看”相信很多人都玩过。没玩过也没关系,下面我给大家介绍一下游戏规则:在一个棋盘中,放了很多的棋子。如果某两个相同的棋子,可以通过一条线连起来 (这条线不能经过其它棋子),而且线的转折次数不超过两次,那么这两个棋子就可以在棋盘上消去。不好意思,由于我以前没有玩过连连看,咨询了同学的意见, 连线不能从外面绕过去的,但事实上这是错的。现在已经酿成大祸,就只能将错就错了,连线不能从外围绕过。
玩家鼠标先后点击两块棋子,试图将他们消去,然后游戏的后台判断这两个方格能不能消去。现在你的任务就是写这个后台程序。
 

Input

输 入数据有多组。每组数据的第一行有两个正整数n,m(0<n<=1000,0<m<1000),分别表示棋盘的行数与列数。在接 下来的n行中,每行有m个非负整数描述棋盘的方格分布。0表示这个位置没有棋子,正整数表示棋子的类型。接下来的一行是一个正整数 q(0<q<50),表示下面有q次询问。在接下来的q行里,每行有四个正整数x1,y1,x2,y2,表示询问第x1行y1列的棋子与第 x2行y2列的棋子能不能消去。n=0,m=0时,输入结束。
注意:询问之间无先后关系,都是针对当前状态的!
 

Output

每一组输入数据对应一行输出。如果能消去则输出"YES",不能则输出"NO"。
 

Sample Input
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
 

Sample Output
YES
NO
NO
NO
NO
YES
   
  姑且能够算一道模拟题吧,计算两点能否通过不超过两次转弯的线相连,并且这条线路上不能够有阻挡物,刚开始的时候可以做一些判定来剪枝,比如是否为同一点,是否是同一图案以及是否有一点为0,即没有图案。
  这道题将BFS做一点小小的变形,即每次让一个方向的可能点全部入对列,这样能够使得拐弯次数限制到最小,标记的变量要设四个方向,每次走过的点要标记两个方向,向前和向后,显然不可能再次走到这一点以相同的方向或者反过来。其他就和一般的BFS差不多了。
4384995 2011-08-11 11:43:41 Accepted 1175 281MS 26284K 2109 B G++ Lyush
  代码如下:
#include <cstdio>
#include <cstring>
#include <queue>
#include <cstdlib>
#define INF 0x7f7f7f7f
using namespace std;

int map[1005][1005], hash[4][1005][1005], dir[4][2]= { 1, 0, -1, 0, 0, 1, 0, -1 };

struct Node
{
	int x, y, type, ti, dir;
}info;

void gint( int &t )
{
	char c;
	while( c= getchar(), c< '0'|| c> '9' ) ;
	t= c- '0';
	while( c= getchar(), c>= '0'&& c<= '9' )
	{
		t= t* 10+ c- '0';
	}
}

bool BFS( int sx, int sy, int ex, int ey )
{
	queue< Node >q;
	memset( hash, 0, sizeof( hash ) );
	info.x= sx, info.y= sy, info.type= map[sx][sy], info.ti= 0, info.dir= -1;
	hash[0][sx][sy]= hash[1][sx][sy]= hash[2][sx][sy]= hash[3][sx][sy]= 1;
	q.push( info );
	while( !q.empty() )
	{
		Node pos= q.front();
		q.pop();
		if( pos.x== ex&& pos.y== ey )
		{
			return true;
		}
		for( int i= 0; i< 4; ++i )
		{
			int x= pos.x+ dir[i][0], y=pos.y+ dir[i][1], ti= pos.ti, d= pos.dir;
			while( ( map[x][y]== 0|| ( x== ex&& y== ey ) )&& !hash[i][x][y] )
			{
				int k= ( i== d|| d== -1 )? 0: 1;
				info.x= x, info.y= y, info.ti= ti+ k, info.dir= i;
				if( info.ti<= 2 )
				{
				    if( info.ti< 2|| ( info.ti== 2 && ( x== ex|| y== ey ) ) )
				    {
					    q.push( info );
				    } 
					hash[i][x][y]= 1;
					if( i== 0|| i== 1 )
					{
					    hash[!i][x][y]= 1;
					}
					else if( i== 2 )
					{
					    hash[3][x][y]= 1;
					}
					else
					{
					    hash[2][x][y]= 1;
					}
				}
				x+= dir[i][0], y+= dir[i][1];
			}
		}
	}
	return false;
}

int main()
{
	int N, M;
	while( scanf( "%d %d", &N, &M ), N| M )
	{
		memset( map, 0x7f, sizeof( map ) );
		for( int i= 1; i<= N; ++i )
		{
			for( int j= 1; j<= M; ++j )
			{
				gint( map[i][j] );
			}
		}
		int q;
		scanf( "%d", &q );
		while( q-- )
		{
			int sx, sy, ex, ey;
			scanf( "%d %d %d %d", &sx, &sy, &ex, &ey );
			if( ( map[sx][sy]!= map[ex][ey] )|| map[sx][sy]== 0|| map[ex][ey]== 0|| ( sx== ex&& sy== ey ) )
			{
				puts( "NO" );
				continue;
			}
			printf( BFS( sx, sy, ex, ey )? "YES\n": "NO\n" );
		}
	}
	return 0;
}

posted @ 2011-08-09 18:20  沐阳  阅读(1023)  评论(0编辑  收藏  举报