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 }