HDU-1175 连连看

连连看

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

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

考虑广搜:从起点s出发,判断能否到达终点e,能到达,则输出YES;否则输出NO

剪枝部分:

       1.若当前点已有棋子(即map[i][j]!=0),继续下一层循环

       2.已被访问的节点用f数组标记并不再访问

       3.转弯次数。转弯次数用turn统计,点当前的方向用di标记。默认起点转弯次数和方向都为-1,此后每个点的方向为dir数组中的i值,若当前点的方向与上一个点的方向不同,则转弯次数加1。当转弯次数大于2时,剪枝。

注:此题用广搜存在严重bug,建议深搜。

bug简要:如上图测试数据,当从(3,4)->(1,1)时,路径为(3,4),(2,4),(2,3),(2,2),(2,1),(1,1)输出YES;但从(1,1)到(3,4)时,路径为(1,1),(1,2),(2,2),(2,3),(2,4),(3,4),由于转弯次数为3次,输出NO,而正确路径应为(1,1),(2,1),(2,2),(2,3),(2,4),(3,4),输出YES

可能是出题人考虑到了这个问题也说不定233

下面附上AC广搜代码

//time = 61ms
#include <iostream>
#include <cstring>
#include <queue>
#include <algorithm>
using namespace std;

struct Node {
	int x;
	int y;
	int turn;
	int dir;

	bool operator ==( const Node bb ) {
		return x==bb.x && y==bb.y;
	}
};

int n,m;
int dir[4][2] = { { -1,0 } , { 0,1 } , { 1,0 } , { 0,-1 } };
bool f[1010][1010];
int map[1010][1010];

bool bfs( Node s , Node e ) {
	queue<Node> q;
	memset( f,false,sizeof(f) );
	q.push(s);
	f[s.x][s.y] = 1;
	Node r,p;
	while( !q.empty() ) {
		r = q.front();
		q.pop();
		for( int i=0 ; i<4 ; i++ ) {
			p.x = r.x + dir[i][0];
			p.y = r.y + dir[i][1];
			p.dir = i;
			if( r.dir==-1 )
				p.turn = 0;
			else
				p.turn = r.dir==i ? r.turn : r.turn+1;
			if( p.turn>2 || p.x<=0 || p.y<=0 || p.x>n || p.y>m || f[p.x][p.y] )
				continue;
			if( p==e ) {
				return true;
			}
			if( map[p.x][p.y]==0 ) {
				q.push(p);
				f[p.x][p.y] = 1;
			}
		}
	}
	return false;
}

int main() {
//	freopen( "in.txt","r",stdin );
	std::ios::sync_with_stdio( false );
	int t;
	Node s,e;
	while( cin >> n >> m && n && m ) {
		for( int i=1 ; i<=n ; i++ ) {
			for( int j=1 ; j<=m ; j++ ) {
				cin >> map[i][j];
			}
		}
		cin >> t;
		while( t-- ) {
			cin >> s.x >> s.y >> e.x >> e.y;
			if( map[s.x][s.y]!=map[e.x][e.y] || map[s.x][s.y]==0 || map[e.x][e.y]==0 )
				goto PN;
			s.turn = s.dir = -1;
			if( bfs( s,e ) ) {
				cout << "YES" << endl;
				continue;
			}
PN:
			cout << "NO" << endl;
		}
	}
}

深搜代码,思路基本相同

//time = 4024ms
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;

struct Node {
	int x;
	int y;
	int turn;
	int dir;

	bool operator ==( const Node bb ) {
		return x==bb.x && y==bb.y;
	}
};

int n,m;
int dir[4][2] = { { -1,0 } , { 0,1 } , { 1,0 } , { 0,-1 } };
bool f[1010][1010];
int map[1010][1010];

bool dfs( Node s , Node e ) {
	f[s.x][s.y] = 1;
	Node p;
	for( int i=0 ; i<4 ; i++ ) {
		p.x = s.x + dir[i][0];
		p.y = s.y + dir[i][1];
		p.dir = i;
		if( s.dir==-1 )
			p.turn = 0;
		else
			p.turn = s.dir==i ? s.turn : s.turn+1;
		if( p.turn>2 || p.x<=0 || p.y<=0 || p.x>n || p.y>m || f[p.x][p.y] )
			continue;
		if( p==e ) {
			return true;
		}
		if( map[p.x][p.y]!=0 )
			continue;
		if( dfs( p,e ) )
			return true;
	}
	f[s.x][s.y] = 0;
	return false;
}

int main() {
//	freopen( "in.txt","r",stdin );
	std::ios::sync_with_stdio( false );
	int t;
	Node s,e;
	while( cin >> n >> m && n && m ) {
		for( int i=1 ; i<=n ; i++ ) {
			for( int j=1 ; j<=m ; j++ ) {
				cin >> map[i][j];
			}
		}
		cin >> t;
		while( t-- ) {
			cin >> s.x >> s.y >> e.x >> e.y;
			if( map[s.x][s.y]!=map[e.x][e.y] || map[s.x][s.y]==0 || map[e.x][e.y]==0 )
				goto PN;
			s.turn = s.dir = -1;
			memset( f,false,sizeof(f) );
			if( dfs( s,e ) ) {
				cout << "YES" << endl;
				continue;
			}
PN:
			cout << "NO" << endl;
		}
	}
}

猜你喜欢

转载自blog.csdn.net/Revenant_Di/article/details/81460546
今日推荐