DFS迷宫问题和优化 java
X星球的一处迷宫游乐场建在某个小山坡上。 它是由10x10相互连通的小房间组成的。房间的地板上写着一个很大的字母。 我们假设玩家是面朝上坡的方向站立,则: L表示走到左边的房间, R表示走到右边的房间,U表示走到上坡方向的房间, D表示走到下坡方向的房间。
X星球的居民有点懒,不愿意费力思考在这里插入代码片。 他们更喜欢玩运气类的游戏。这个游戏也是如此!开始的时候,直升机把100名玩家放入一个个小房间内。 玩家一定要按照地上的字母移动。UDDLUULRUL
UURLLLRRRU
RRUURLDLRD
RUDDDDUUUU
URUDLLRRUU
DURLRLDLRL
ULLURLLRDU
RDLULLRDDD
UUDDUDUDLL
ULRDLUURRR
答案
31
分析
- 从第一个点U开始按照字母走,设一个10x10的数组,每当数组下标越界,代表走出去
- 然后进行下个点的进入。根据UDLR进行 行列坐标的移动。
另一种方法直接数
在写的时候发现两个小问题
1.java不能直接输入字符型;
2.java的Arrays.fill()方法只能对一维数组赋值;
解决
对二维数组赋值
import java.util.Arrays;
import java.util.Scanner;
public class DFS_1 {
static char[][] map = new char[11][11];//存储迷宫
static boolean[][] vis = new boolean[12][12];//存储是否访问
public static void main(String[] args) {
// TODO Auto-generated method stub
Scanner input = new Scanner(System.in);
String a;
int ans = 0;
for (int i = 0; i < 10; i++) {
a = input.next();//由于java没有输入字符型,先输入一行
map[i] = a.toCharArray();//将该行转换为字符型
}
for (int i = 0; i < 10; i++) {//对每个点判断能否走出
for (int j = 0; j < 10; j++) {
for (int m= 0; m < 10; m++) {//搜点前,每次将二位数组vis全设为FALSE
Arrays.fill(vis[m], false);//该方法只能将一维数组设为False
}
if (dfs(i, j)) {
ans++;
}
}
}
System.out.println(ans);
}
private static boolean dfs(int i, int j) {
if (i>9||i < 0 || j > 9||j<0)//出来后返回true
return true;
if (vis[i][j]) {//如果访问过,代表又开始访问,就认为,它在兜圈子;返回false;
return false;
}
vis[i][j] = true;//访问中。。。
if (map[i][j] == 'U') {//上
return dfs(i - 1, j);
}
if (map[i][j] == 'D') {//下
return dfs(i + 1, j);
}
if (map[i][j] == 'R') {//右
return dfs(i, j + 1);
}
if (map[i][j] == 'L') {//左
return dfs(i, j - 1);
}
return false;
}
}
增加了一个memory数组记录已经走过的点,如果该点能出去设为1,不能出去设为2,避免一个路径与好几个路径重合,进行重复访问
import java.util.Arrays;
import java.util.Scanner;
public class DFS_1的优化 {
static char[][] map = new char[11][11];// 存储迷宫
static boolean[][] vis = new boolean[12][12];// 存储是否访问
static int count;
static int[][] memory = new int[11][11];
public static void main(String[] args) {
// TODO Auto-generated method stub
Scanner input = new Scanner(System.in);
String a;
int ans = 0;
for (int i = 0; i < 10; i++) {
a = input.next();// 由于java没有输入字符型,先输入一行
map[i] = a.toCharArray();// 将该行转换为字符型
}
for (int i = 0; i < 10; i++) {// 对每个点判断能否走出
for (int j = 0; j < 10; j++) {
for (int m = 0; m < 10; m++) {// 搜点前,每次将二位数组vis全设为FALSE
Arrays.fill(vis[m], false);// 该方法只能将一维数组设为False
}
if (dfs(i, j)) {
ans++;
}
}
}
System.out.println(ans);
System.out.println(count);
}
private static boolean dfs(int i, int j) {
count++;
if (i > 9 || i < 0 || j > 9 || j < 0)// 出来后返回true
{
return true;
}
if (vis[i][j]) {// 如果访问过,代表又开始访问,就认为,它在兜圈子;返回false;
return false;
}
if (memory[i][j] == 1) {//如果该点能出去设为1,不能出去设为2
return true;
}
if (memory[i][j] == 2) {
return false;
}
vis[i][j] = true;// 访问中。。。
if (map[i][j] == 'U') {// 上
if (dfs(i - 1, j)) {
memory[i][j] = 1;
return true;
} else {
memory[i][j] = 2;
return false;
}
}
if (map[i][j] == 'D') {// 下
if (dfs(i +1, j)) {
memory[i][j] = 1;
return true;
} else {
memory[i][j] = 2;
return false;
}
}
if (map[i][j] == 'R') {// 右
if (dfs(i , j+1)) {
memory[i][j] = 1;
return true;
} else {
memory[i][j] = 2;
return false;
}
}
if (map[i][j] == 'L') {// 左
if (dfs(i, j-1)) {
memory[i][j] = 1;
return true;
} else {
memory[i][j] = 2;
return false;
}
}
return false;
}
}