连连看游戏(dfs)【华为上机题目】
1 连连看游戏
今天同学给我做了道编程题目,貌似是华为的,题目描述大概是这样的:
给定一个连连看棋盘,棋盘上每个点都有各种图案(用非0数字表示),输入棋盘上的任意两个左标,判断这两个坐标对应的图案是否可以消除,消除的条件是图案相同且图案间连线的转角数不得超过2。例如有下面一个棋盘:
1 3 3 4
0 6 0 0
4 0 2 1
6 0 4 2
在棋盘中,(0,1)和(0,2)中的图案没有转角可以消除,(1,1)和(3,0)中的6有一个转角可以可以消除,(2,0)和(3,2)中的4有两个转角可以消除,而(0,0)和(2,3)中的1不能消去。
输入数据为连续的整数,第一个数为棋盘的行数m,第二个数为棋盘的列数n,然后依次是m*n个棋盘数据,最后是两个坐标对应的行号和列号。
如果图案不能消除,输出0, 如果图案可以消除,输出图案消除路线上图案的个数(包含输入的两个图案,不考虑有多条可消除路径的情况)。
例如输入4,4,1,3,3,4,0,6,0,0,4,0,2,1,6,0,4,2,2,0,3,2(棋盘的数据就是上面例子中的数据)
输出为4,输入是一个4*4的棋盘,最后两个图案的坐标为(2,0)和(3,2),中间为棋盘中的数据。
看这题目本来是不难的,不过题目的输出看了半天没理解,“输出图案消除路线上图案的个数”是路线上连接的图案吗?两个图案直接的路线连接不是不能有图案吗?纠结了半天还是不懂什么意思。最后只能理解是两个图案所连接的线路中坐标点的个数了(不知道理解的对不对),如果这样理解的话题目就不是很难了,就是对于两个给定的坐标点能否联通,并且连接连个坐标点的路径上不能超过两个拐角就行了,用一般的dfs就可以解决。不过这道题目中路径上的拐角可以帮助用来减少搜索的深度,即当前搜索的路径已经超过了两个拐角之后直接忽略该条路径的搜索。本来搜索时为了防止搜索已经搜索的坐标,坐标位置是要做标记的,不过因为路线最多出现两个拐角,所以不可能出现这种情况,要出现这种情况必须至少要三个拐角。还有就是为了尽量减少搜索路径出现的拐角数量,搜索的方向尽量保持不要改变,即如果能不改变方向,则优先搜索这个方向,之所以可以这样做是因为题目只要求找出一条满足条件的路径就可以了。具体见下面的代码:
1 #include <iostream> 2 #include <stdio.h> 3 4 int **data; 5 int m, n, ans; 6 int start_x, start_y, end_x, end_y; 7 int move[4][2] = {{0, 1}, {1, 0}, {0, -1}, {-1, 0}}; 8 9 int dfs(int x, int y, int count, int gj, int dir) 10 { 11 if (gj > 2) 12 return 0; 13 if (x == end_x && y == end_y) 14 { 15 ans = count; 16 return 1; 17 } 18 int x1, y1; 19 if (count > 1) //优先考虑上一步和当前步的方向保持一致 20 { 21 x1 = x + move[dir][0]; 22 y1 = y + move[dir][1]; 23 if (x1 >= 0 && x1 < m && y1 >= 0 && y1 < n && !data[x1][y1]) 24 { 25 if (dfs(x1, y1, count + 1, gj, dir)) 26 return 1; 27 } 28 } 29 for (int i = 0; i < 4; i++) 30 { 31 if (count > 1 && i == dir) 32 continue; 33 x1 = x + move[i][0]; 34 y1 = y + move[i][1]; 35 if (x1 >= 0 && x1 < m && y1 >= 0 && y1 < n && 36 !data[x1][y1] && (count == 1 || ((i + 2) % 4) != dir)) //无须考虑当前步方向与前一步方向相反 37 { 38 if (dfs(x1, y1, count + 1, (i == dir || count == 1) ? gj : gj + 1, i)) 39 return 1; 40 } 41 42 } 43 return 0; 44 } 45 int main(void) 46 { 47 freopen("in.txt", "r", stdin); 48 49 char temp; 50 int i, j; 51 52 std::cin >> m >> temp >> n >> temp; 53 data = new int *[m]; 54 for (i = 0; i < m; i++) 55 data[i] = new int[n]; 56 57 for (i = 0; i < m; i++) 58 for (j = 0; j < n; j++) 59 std::cin >> data[i][j] >> temp; 60 std::cin >> start_x >> temp >> start_y >> temp >> end_x >> temp >> end_y; 61 ans = 0; 62 data[end_x][end_y] = 0; 63 dfs(start_x, start_y, 1, 0, 0); 64 std::cout << ans << std::endl; 65 return 0; 66 }