题目描述: 输入一个二维字符数组map和一个字符串数组word,判断word中的元素是否在map中有相应的路径存在,其中map中的路径可以上下左右各走一格。如果存在输出 Has,如果不存在输出 Not Has。
像Word中的第一行在Map中第一列存在,Word中的第二行在Map中的第三行存在,....
解题思路:本题使用回溯法,深度优先搜素遍历二维字符数组中的元素,寻找可能存在的路径。
代码如下:
public class Test {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
System.out.println("请输入map的行数:");
int n = sc.nextInt();
System.out.println("请输入map的列数:");
int m = sc.nextInt();
System.out.println("请输入word的行数:");
int q = sc.nextInt();
System.out.println("请输入map的元素:");
char[][] map = new char[n][m];
for(int i = 0; i < n; i++) {
String s = sc.next();
char[] c = s.toCharArray();
map[i] = c;
}
System.out.println("请输入word的元素: ");
String[] word = new String[q];
for(int i =0; i < q; i++) {
word[i] = sc.next();
}
CheckString(map, n, m, word);
}
//检查字符数组中是否有指定的字符串路径
public static void CheckString(char[][] map, int n, int m, String[] word){
//分别取字符串数组中的每个字符串
for(int i=0;i<word.length;i++) {
//将字符串转换为一维char字符数组
char[] ch = word[i].toCharArray();
Check(map,n,m,ch,i);
}
}
//
public static void Check(char[][]map, int n, int m, char[]ch,int flag){
//定义一维访问矩阵,记录每次二维字符数组中字符是否被访问
boolean[] visited = new boolean[n*m];
//初始化访问矩阵
for(int i=0;i<n;i++) {
for(int j=0;j<m;j++) {
visited[i*m+j] =false;
}
}
boolean has = false;
//遍历二维数组中的所有元素
out:for(int i=0;i<n;i++) {
for(int j=0;j<m;j++) {
has = CheckVisited(map, i, j, n, m, ch, 0, flag, visited);
if(has)
break out;
}
}
if(has) {
System.out.println("case: " + flag + " Has");
}else {
System.out.println("case: " + flag + " Not Has");
}
}
//如果二维数组中存在匹配字符串的路径,则返回true,否则返回false
public static boolean CheckVisited(char[][]map, int a, int b, int n, int m, char[]ch, int i,int flag, boolean[]visited) {
//递归调用的约束条件
if(a>=0&&b>=0&&a<n&&b<m&&!visited[a*m+b]&&i<ch.length&&ch[i]==map[a][b]) {
i++;
visited[a*n+b]=true;
return CheckVisited(map,a,b-1,n,m,ch,i,flag,visited)||CheckVisited(map,a+1,b,n,m,ch,i,flag,visited)
||CheckVisited(map,a,b+1,n,m,ch,i,flag,visited)||CheckVisited(map,a-1,b,n,m,ch,i,flag,visited);
}
if(i==ch.length-1) {
return true;
}
return false;
}
}
运行结果: