连连看
Time Limit: 20000/10000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)
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
这个题之所以我现在还把它放在这里:
(1) 和一般的dfs有点小区别
(2) 当前的访问点(x,y)不能随意标记已访问 。
(2) 对于每个点应该抽象成为12种情况
(A,B )
A : 方向(4种)
B : 转折次数 (3种)
很多人说这个题数据有毛病,其实是没有搞清楚实质。
#include <iostream> #include <string> #include <string.h> #include <map> #include <stdio.h> #include <algorithm> #include <queue> #include <vector> #include <math.h> #include <set> #define Max(a,b) ((a)>(b)?(a):(b)) #define Min(a,b) ((a)<(b)?(a):(b)) #pragma comment(linker, "/STACK:16777216") using namespace std ; typedef long long LL ; int chess[1008][1008] ; bool visited[1008][1008][4][3] ; class LLK{ private : int N ; int M ; static int d[4][2] ; public : LLK() ; LLK(int ,int) ; void read() ; int cango(int,int) ; int dfs(int ,int ,int ,int ,int ,int) ; void gao() ; }; LLK::LLK(){ } LLK::LLK(int n ,int m):N(n),M(m){ } int LLK::d[4][2] = {{-1,0},{0,-1},{1,0},{0,1}} ; void LLK::read(){ for(int i = 1 ;i <= N ;i++) for(int j = 1 ;j <= M ;j++) scanf("%d",&chess[i][j]) ; } int LLK::cango(int x ,int y){ return 1<=x&&x<=N&&1<=y&&y<=M ; } int LLK::dfs(int x ,int y,int ex,int ey ,int direc ,int turn){ if(direc != -1) visited[x][y][direc][turn] = 1 ; if(x == ex && y== ey) return 1 ; for(int i = 0 ; i < 4 ;i++){ int nx = x + d[i][0] ; int ny = y + d[i][1] ; int nd ,nt; if(!cango(nx,ny)) continue ; if((chess[nx][ny] != 0) && !(nx == ex && ny == ey)) continue ; if(direc == -1) nt = 0 ; else if(direc == i) nt = turn ; else nt = turn + 1 ; nd = i ; if(visited[nx][ny][nd][nt]) continue ; if(turn > 2) continue ; if(dfs(nx,ny,ex,ey,nd,nt)) return 1 ; } return 0 ; } void LLK::gao(){ int q ,sx ,sy,ex,ey ; scanf("%d",&q) ; while(q--){ scanf("%d%d%d%d",&sx,&sy,&ex,&ey) ; if(chess[sx][sy] != chess[ex][ey]) puts("NO") ; else if(chess[sx][sy] == 0 || chess[ex][ey] == 0) puts("NO") ; else{ memset(visited,0,sizeof(visited)) ; if(dfs(sx,sy,ex,ey,-1,0)) puts("YES") ; else puts("NO") ; } } } int main(){ int n , m ; while(scanf("%d%d",&n,&m)){ if(n == 0 && m == 0) break ; LLK llk(n,m) ; llk.read() ; llk.gao() ; } return 0 ; }