題目描述
請設計一個函數,用來判斷在一個矩陣中是否存在一條包含某字元串所有字元的路徑。路徑可以從矩陣中的任意一個格子開始,每一步可以在矩陣中向左,向右,向上,向下移動一個格子。如果一條路徑經過了矩陣中的某一個格子,則該路徑不能再進入該格子。
例如:
a b c e
s f c s
a d e e
矩陣中包含一條字元串"bcced"的路徑,但是矩陣中不包含"abcb"路徑,因為字元串的第一個字元b占據了矩陣中的第一行第二個格子之後,路徑不能再次進入該格子。
參考問題:
馬踏棋盤 : 将馬随機放在國際象棋的 8x8 [0~7][0~7]的某個方格中,馬按走棋(日字走法)規則進行移動。每個格子隻能走一邊,走遍棋盤上全部64個方格。求出馬的行走路線,并按求出的行走路線,将數字1,2,…,64依次填入一個8×8的方陣,輸出之。
分析:
此題可采用回朔法。首先在格子中任選一個格子作為路徑起點,然後在上下左右的位置尋找下一步,尋找到則進入下一步,若上下左右均沒有下一步,則傳回上一步的位置從上一步尋找新的路徑。矩陣還需一個對應的bool表,來記錄走過的路徑。
Java實作代碼如下:
1 import java.util.*;
2
3 public class Solution {
4
5 public boolean hasPath(char[] matrix, int rows, int cols, char[] str) {
6 if(matrix==null || matrix.length==0 || str==null || str.length==0 || matrix.length!=rows*cols || rows<=0 || cols<=0 || rows*cols < str.length) {
7 return false ;
8 }
9
10 boolean[] visited = new boolean[rows*cols] ;
11 int[] pathLength = {0} ;
12
13 for(int i=0 ; i<=rows-1 ; i++) {
14 for(int j=0 ; j<=cols-1 ; j++) {
15 if(hasPathCore(matrix, rows, cols, str, i, j, visited, pathLength)) { return true ; }
16 }
17 }
18
19 return false ;
20 }
21
22 public boolean hasPathCore(char[] matrix, int rows, int cols, char[] str, int row, int col, boolean[] visited, int[] pathLength) {
23 boolean flag = false ;
24
25 if(row>=0 && row<rows && col>=0 && col<cols && !visited[row*cols+col] && matrix[row*cols+col]==str[pathLength[0]]) {
26 pathLength[0]++ ;
27 visited[row*cols+col] = true ;
28 if(pathLength[0]==str.length) { return true ; }
29 flag = hasPathCore(matrix, rows, cols, str, row, col+1, visited, pathLength) ||
30 hasPathCore(matrix, rows, cols, str, row+1, col, visited, pathLength) ||
31 hasPathCore(matrix, rows, cols, str, row, col-1, visited, pathLength) ||
32 hasPathCore(matrix, rows, cols, str, row-1, col, visited, pathLength) ;
33
34 if(!flag) {
35 pathLength[0]-- ;
36 visited[row*cols+col] = false ;
37 }
38 }
39
40 return flag ;
41 }
42
43 }
C++實作如下:
1 boolean hasPath(char[] matrix, int rows, int cols, char[] str) {
2 int flag[] = new int[matrix.length];
3 for (int i = 0; i < rows; i++) {
4 for (int j = 0; j < cols; j++) {
5 if (helper(matrix, rows, cols, i, j, str, 0, flag))
6 return true;
7 }
8 }
9 return false;
10 }
11
12 boolean helper(char[] matrix, int rows, int cols, int i, int j, char[] str, int k, int[] flag) {
13 int index = i * cols + j;
14 if (i < 0 || i >= rows || j < 0 || j >= cols || matrix[index] != str[k] || flag[index] == 1)
15 return false;
16 if(k == str.length - 1) return true;
17 flag[index] = 1;
18 if (helper(matrix, rows, cols, i - 1, j, str, k + 1, flag)
19 || helper(matrix, rows, cols, i + 1, j, str, k + 1, flag)
20 || helper(matrix, rows, cols, i, j - 1, str, k + 1, flag)
21 || helper(matrix, rows, cols, i, j + 1, str, k + 1, flag)) {
22 return true;
23 }
24 flag[index] = 0;
25 return false;
26 }
參考問題分析:
與上問題相似,需要的是一個8x8的數組,起始均為0,第一步走的格子填1,第二步填2....直至64,說明棋盤周遊完成。遞歸實作如下。
1 #include<stdio.h>
2 #include <stdlib.h>
3 #include<conio.h>
4 #define N 8
5 int cnt=1; // 記錄馬的位置
6 int n=1;
7 int chess[8][8]={0}; //棋盤
8 int move[8][2]={
9 {1,-2},{2,-1},
10 {2,1},{1,2},
11 {-1,2},{-2,1},
12 {-2,-1},{-1,-2}
13 };
14 void horse(int ,int );
15 void printhorse();
16
17 int main() //主函數
18 {
19 chess[0][0]=1;
20 horse(0,0);
21 return 0;
22 }
23 void horse(int x,int y) //執行過程
24 {
25 int i;
26 int a,b;
27 for(i=0;i<N;i++)
28 {
29 a=x+move[i][0];
30 b=y+move[i][1];
31 if(a>=0&&a<N&&b>=0&&b<N&&!chess[a][b])
32 {
33 chess[a][b]=++cnt;
34 if(cnt<64)
35 { horse(a,b);
36
37 } // 遞歸
38 else{
39 printhorse();
40 // exit(0);
41
42
43 }
44 chess[a][b]=0;//修改ab的值歸為0
45 cnt--;
46 }
47 }
48 }
49 void printhorse() //輸出馬踏棋盤
50 {
51 int i,j;
52 printf("輸出第%d中解法:\n",n++);
53 for(i=0;i<N;i++)
54 {
55 for(j=0;j<N;j++)
56 printf("%3d ",chess[i][j]);
57 printf("\n");
58 }
59 }