HDU-OJ-1175 连连看
2014-03-11 19:53
225 查看
连连看
[align=center]Time Limit: 20000/10000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)[/align]
[align=left]Problem Description[/align]
“连连看”相信很多人都玩过。没玩过也没关系,下面我给大家介绍一下游戏规则:在一个棋盘中,放了很多的棋子。如果某两个相同的棋子,可以通过一条线连起来(这条线不能经过其它棋子),而且线的转折次数不超过两次,那么这两个棋子就可以在棋盘上消去。不好意思,由于我以前没有玩过连连看,咨询了同学的意见,连线不能从外面绕过去的,但事实上这是错的。现在已经酿成大祸,就只能将错就错了,连线不能从外围绕过。
玩家鼠标先后点击两块棋子,试图将他们消去,然后游戏的后台判断这两个方格能不能消去。现在你的任务就是写这个后台程序。
[align=left]Input[/align]
输入数据有多组。每组数据的第一行有两个正整数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时,输入结束。
注意:询问之间无先后关系,都是针对当前状态的!
[align=left]Output[/align]
每一组输入数据对应一行输出。如果能消去则输出"YES",不能则输出"NO"。
[align=left]Sample Input[/align]
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
[align=left]Sample Output[/align]
YES
NO
NO
NO
NO
YES
[align=left]Author[/align]
lwg
——————————————————————帅气分割线——————————————————————
思路:这不是我麻麻最喜欢玩的游戏嘛?!没想到写出来它酱不容易。需要在大脑中多开辟一个维度。哦不,是两个维度……其实,都一样嘛!需要有一个想法:增加状态。用状态控制DFS。从起点开始遍历地图,直到找到了终点为止,在此期间,转向次数不得超过2。我们知道DFS是一条路走到黑的,那么一旦此路不通,需要回到上一个还有路没试过的点。什么时候一个点算是彻底不必再访问呢?答案是:1.到该点时已经转向一次,四个方向都不通 2.到该点时已经转向两次,四个方向都不通。vis[x][y][direction][turn]浮现在脑海里。此外,有很多补丁需要打,尤其针对“方向”这个状态量。
这就是附加状态的vis数组。
代码如下:
#include <stdio.h> #include <string.h> #include <math.h> #include <memory.h> #include <stdlib.h> #define LIM nx >= 1 && nx <= n && ny >=1 && ny <= m int a[1010][1010]; bool vis[1010][1010][4][2]; int n, m, q, flag; int sx, sy, ex, ey; int dx[4] = {-1, 0, 1, 0}, dy[4] = {0, 1, 0, -1}; void dfs(int x, int y, int dir, int t){ int d; if(t > 2 || flag) return ;//转向次数超过2或者已经断定可以配对,回城 if(x == ex&&y == ey){//走到了终点 flag = 1; return ; } vis[x][y][dir][t] = 1;//对该转向次数该访问方向下的该结点做访问标记 for(d = 0; d < 4; d++){ int nx = x+dx[d], ny = y+dy[d]; if(!vis[nx][ny][d][t+(d != dir)] && !a[nx][ny] && LIM) dfs(nx, ny, d, t+(d != dir));//t+(d != dir) 是对转向与否的判断。方向与父方向不一致,转向加1 } return ; } int main(){ int i, j, d; while(scanf("%d%d", &n, &m) != EOF&&n||m){ for(i = 1; i <= n; i++) for(j = 1; j <= m; j++) scanf("%d", a[i]+j); scanf("%d", &q);//询问次数 while(q--){ flag = 0; scanf("%d%d%d%d", &sx, &sy, &ex, &ey); if(a[sx][sy] != a[ex][ey]) puts("NO");//起点和终点不是同样的方块,不能配对 else if(!a[sx][sy] || !a[ex][ey]) puts("NO");//终点或者起点有一个设在了什么都没有的地方,不能配对 else{//下面在主函数内,对“方向”等等打出补丁 int u = a[ex][ey];//首先保存终点方块的样子 a[ex][ey] = 0;//接着将其置为0,不然无法访问终点 memset(vis, 0, sizeof(vis)); for(d = 0; d < 4; d++){//从起点开始,有四个方向需要尝试,仅仅走能走通的方向,若不如此做,初始方向无法确定!默认是0(上)的话,vis数组就会出错 int x1 = sx+dx[d], y1 = sy+dy[d]; if(a[x1][y1] == 0) dfs(x1, y1, d, 0); } a[ex][ey] = u;//这个补丁很重要!不恢复终点的样子,下次在“起点或终点有一个为0”的特判会出错! if(flag) puts("YES"); else puts("NO"); } } } return 0; }
相关文章推荐
- hdu 1175 连连看 (简单DFS)
- HDU 1175 连连看
- hdu 1175 连连看 bfs
- HDU-1175 连连看 DFS
- hdu 1175 连连看
- hdu1175 连连看
- HDU 1175 连连看【BFS】
- 【dfs】hdu 1175 连连看
- HDU 1175 连连看【BFS】
- HDU - 1175 连连看(dfs)
- hdu 1175:连连看(dfs 深度优先搜索)
- hdu 1175 DFS连连看
- hdu 1175 连连看
- HDU 1175 连连看(BFS)
- hdu 1175 连连看 DFS+剪枝
- HDU1175 连连看
- dfs-HDU 1175 连连看
- HDU 1175 连连看
- 【hdu 1175】 连连看 题解 (c++)
- HDU 1175 连连看(BFS)