题目描述
请设计一个函数,用来判断在一个矩阵中是否存在一条包含某字符串所有字符的路径。路径可以从矩阵中的任意一个格子开始,每一步可以在矩阵中向左,向右,向上,向下移动一个格子。如果一条路径经过了矩阵中的某一个格子,则该路径不能再进入该格子。
例如:
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 }