hdu 1175 连连看
来源:互联网 发布:阿里云服务器老是掉线 编辑:程序博客网 时间:2024/05/21 13:57
Time Limit: 20000/10000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 10223 Accepted Submission(s): 2690
Total Submission(s): 10223 Accepted Submission(s): 2690
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 41 2 3 40 0 0 04 3 2 141 1 3 41 1 2 41 1 3 32 1 2 43 40 1 4 30 2 4 10 0 0 021 1 2 41 3 2 30 0
Sample Output
YESNONONONOYES
题意: 连连看。 就是给你一个N*M 的棋盘。 然后, 有Q次询问, 问两个坐标是否能消去(坐标可以相同)。 规则: 连线只能在棋盘内, 转折 turn <= 2;
思路:深搜。
先别考虑时间, 怎么判断是否转折了。
每次移动都有四个选择, 上, 下, 左, 右, 如图, 我是约定 0 代表 左 1 代表 右, 2 代表 上, 3 代表 下
那么 如果棋子是走 1(右), 3(下), 0(左), 那么就会到达 黄格。
转折了2次, 分别是 在 从 走1 变为 走3 的时候, 和 从 走3 变为 走0 的时候 发生了转折。
如果棋子是走 1 (右), 3( 下), 3(下), 1(右), 1(右) ,那么就会到达 灰格子。
也是发生了两次转折。 分别是从 走1 变为 走3 的时候,和 从 走3 变为 走1 的时候。 而 两次走3 和 两次走1 都未发生转折。
从上面的走法来看,不难发现, 只要当前走的方向与上次走的方向不一样就是 转折了。
那么 左 == (0, -1) 右 == (0, 1) 上 == (-1, 0) 下 == (1, 0);
下面就考虑时间问题啦!
剪枝: 首先 按照规则剪枝 坐标对应的值是0 或者 两坐标对应的值不相等 或者 两坐标相同的 或者 转折大于2的 就输出 (“no")。
然后是最关键的剪枝: 如果 turn == 2 但是 当前位置与 目标位置不在同一直线上就要退出。 因为至少需要一个转折才能让当前位置移动到与目标在同一直线。
if(turn == 2 && x != index_i && y != index_j) return;
如果 当前位置与目标位置在同一直线,但当前移动方向不能移动到 目标位置的。
#include <stdio.h>#include <string.h>#define max_size 1005int num[max_size][max_size], visited[max_size][max_size], index_i, index_j, flag, n, m;int a[4][2] = {1, 0, -1, 0, 0, 1, 0, -1};void dfs(int x, int y, int turn, int index) { if(flag) return;//违背规则的 if(turn > 2) return; if(turn == 2) {//不在同一直线if(x != index_i && y != index_j) return;//在同一列,运动方向不是往目标移动if(x != index_i)if(x - index_i > 0 && index != 1 || x - index_i < 0 && index != 0)return;//在同一行,运动方向不是往目标移动if(y != index_j)if(y - index_j > 0 && index != 3 || y - index_j < 0 && index != 2)return;}//满足条件的 if(turn <= 2 && x == index_i && y == index_j) { flag = 1; return; } for(int i = 0; i < 4; ++i) { int nx = x + a[i][0], ny = y + a[i][1]; if(!visited[nx][ny] && (!num[nx][ny] || nx == index_i && ny == index_j)) { if(i != index && index != -1) turn++; visited[nx][ny] = 1; dfs(nx, ny, turn, i); visited[nx][ny] = 0; if(i != index && index != -1) turn--; } }}int main() { while(scanf("%d%d", &n, &m) && n || m) { for(int i = 0; i <= n + 1; ++i) for(int j = 0; j <= m + 1; ++j) visited[i][j] = -1; for(int i = 1; i <= n; ++i) for(int j = 1; j <= m; ++j) { scanf("%d", &num[i][j]); visited[i][j] = 0; } int Q; scanf("%d", &Q); while(Q--) { int start_i, start_j; scanf("%d%d%d%d", &start_i, &start_j, &index_i, &index_j); flag = 0; if(start_i != index_i || start_j != index_j) if(num[start_i][start_j] == num[index_i][index_j] && num[start_i][start_j] > 0) { visited[start_i][start_j] = 1; dfs(start_i, start_j, 0, -1); visited[start_i][start_j] = 0; } if(flag) printf("YES\n"); else printf("NO\n"); } }}
- hdu 1175 连连看
- hdu 1175 连连看
- hdu 1175 连连看
- HDU 1175 连连看
- HDU 1175 ( 连连看 )
- hdu 连连看 1175
- hdu 1175 连连看
- hdu 1175连连看
- HDU 1175 连连看
- hdu 1175 连连看
- HDU 1175 连连看
- HDU 1175 连连看
- HDU 1175 连连看
- HDU 1175 连连看
- hdu 1175 连连看
- hdu 1175 连连看
- HDU-1175 连连看
- HDU 1175 连连看
- Putty连接虚拟机
- 【linux基础】Valgrind
- C++入门进阶之一: 基础知识介绍
- CSS背景图拉伸自适应尺寸,全浏览器兼容
- eclipse,myeclipse的插件安装
- hdu 1175 连连看
- 详细MSSQL注入语句
- Android SDK更新以及ADT更新出现问题的解决办法
- 如何在Web用户控件中引用样式表中的样式
- GridView 通用分页
- 【基础C&C++】fork和vfork
- AS3多线程快速入门(一):Hello World[
- C# 操作Excel获取数据、时间、图片
- AjaxPro使用方法详解