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"。
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
output
YES
NO
NO
NO
NO
YES
#include<cstdio> #include<cstring> #include<string> #include<queue> using namespace std; struct node{ int x,y,di; }; int map[1005][1005]; int mark[1005][1005]; int lsum,n,m,k,sx,sy,ex,ey; int dir[4][2]={{0, 1}, {0, -1}, {1, 0}, {-1, 0}}; int overmap(int x,int y) { if(x<0||x>=n||y<0||y>=m) return 1; else return 0; } int bfs() { memset(mark, 0, sizeof(mark)); queue<node> Q; node first, next; first.x = sx, first.y = sy; first.di = -1; mark[first.x][first.y] = 0; Q.push(first); while (!Q.empty()) { first = Q.front(); Q.pop(); for (int i = 0; i < 4; i++) { next.x = first.x + dir[i][0]; next.y = first.y + dir[i][1]; next.di = i; if (next.di != first.di) { lsum = mark[first.x][first.y] + 1; } else { lsum = mark[first.x][first.y]; } if (overmap(next.x, next.y)) { continue; } if(mark[next.x][next.y]==0) { if(next.x==ex&&next.y==ey&&map[ex][ey] == map[sx][sy] && lsum <= 3) { return 1;} if(map[next.x][next.y]==0) { mark[next.x][next.y]=lsum; if(lsum==4) continue; Q.push(next); } } } } return 0; } int main() { int i,j; while(scanf("%d%d",&n,&m),n||m) { for(i=0;i<n;i++) for(j=0;j<m;j++) scanf("%d",&map[i][j]); scanf("%d",&k); while(k--) { scanf("%d%d%d%d",&sx,&sy,&ex,&ey); sx--;sy--;ex--;ey--; if (map[sx][sy] != map[ex][ey] || map[sx][sy] == 0 || map[ex][ey] == 0) { printf("NO\n"); continue; } if(bfs())printf("YES\n"); else printf("NO\n"); } } return 0; }
#include<cstdio> #include<cstring> #include<string> #include<queue> using namespace std; struct node{ int x,y,di; }; int map[1005][1005]; int mark[1005][1005]; int lsum,n,m,k,sx,sy,ex,ey; int dir[4][2]={{0, 1}, {0, -1}, {1, 0}, {-1, 0}}; int overmap(int x,int y) { if(x<0||x>=n||y<0||y>=m) return 1; else return 0; } int bfs() { memset(mark, 0, sizeof(mark)); queue<node> Q; node first, next; first.x = sx, first.y = sy; first.di = -1; mark[first.x][first.y] = 0; Q.push(first); while (!Q.empty()) { first = Q.front(); Q.pop(); for (int i = 0; i < 4; i++) { next.x = first.x + dir[i][0]; next.y = first.y + dir[i][1]; next.di = i; if (next.di != first.di) { lsum = mark[first.x][first.y] + 1; } else { lsum = mark[first.x][first.y]; } if (overmap(next.x, next.y)) continue; if(/*lsum <= mark[next.x][next.y]||*/mark[next.x][next.y]==0) //第一:可以只用处理转弯次数为0的,如果转弯次数不为0就不用处理。第二:如果这次的转弯次数比上次的要小,就入队,如果是大于的话,就会出现回路 { if(next.x==ex&&next.y==ey&&map[ex][ey] == map[sx][sy] && lsum <= 3) return 1; if(map[next.x][next.y]==0)//只用处理map[][]为0的 { mark[next.x][next.y]=lsum; if(lsum==4) continue; Q.push(next);//如果map[][]值为0时才可以入队 } } } } return 0; } int main() { int i,j; while(scanf("%d%d",&n,&m),n||m) { for(i=0;i<n;i++) for(j=0;j<m;j++) scanf("%d",&map[i][j]); scanf("%d",&k); while(k--) { scanf("%d%d%d%d",&sx,&sy,&ex,&ey); sx--;sy--;ex--;ey--; if (map[sx][sy] != map[ex][ey] || map[sx][sy] == 0 || map[ex][ey] == 0) { printf("NO\n"); continue; } if(bfs())printf("YES\n"); else printf("NO\n"); } } return 0; }