暴力搜索的思路:
用额外空间记录是否被搜索过,不要想着在原图上进行修改,容易出错
记录条件:当前递归顶点为目标顶点
回溯的条件:只要一个顶点的所有临接路径都被遍历过了,就可以回溯了,而不是一旦触底就回溯。
注意:在思考回溯问题的时候一定要考虑回溯要做什么以及回溯的时机。
package meituan;
import java.util.*;
//1表示经理,2表示商家,0表示可以经过,-1表示不能经过,商家可以上下左右走
//要求返回方案数
//方法一:暴力递归加回溯
//可以转动态规划吗?
//如果转动态规划d[i][j]表示到坐标(i,j)时的方案数
public class Visit {
private int result = 0;
private int[][] dir = {{0,1},{1,0},{0,-1},{-1,0}};
private void dfs(int[][] map,int x,int y,int targetX,int targetY,boolean[][] visit){
//System.out.println();
//抵达目标
if(map[x][y] == 2){
result++;
return;
}
//越界
if(x<0||x>=map.length||y<0||y>=map[0].length){
return;
}
//遇到障碍物或者已经经过
if(visit[x][y]||map[x][y]==-1){
return;
}
//标记为已到达
visit[x][y] = true;
// for (int i = 0; i < map.length; i++) {
// for (int j = 0; j < map[0].length; j++) {
// System.out.print(visit[i][j]+" ");
// }
// System.out.println();
// }
for (int i = 0; i < 4; i++) {
int curX = dir[i][0]+x;
int curY = dir[i][1]+y;
if (curX>=0&&curX<map.length&&curY>=0&&curY<map[0].length&&!visit[curX][curY])
dfs(map,curX,curY,targetX,targetY,visit);
// if(curX>=0&&curX<map.length&&curY>=0&&curY<map[0].length){
// visit[curX][curY] = false;
// }
}
//回溯的条件:其上下左右都走过了一遍就回溯
visit[x][y] = false;
}
public int countPath(int[][] map, int n, int m) {
// write code here
int x = 0;
int y = 0;
int targetX = 0;
int targetY = 0;
for(int i = 0;i<n;i++){
for(int j = 0;j<m;j++){
if(map[i][j]==1){
x = i;
y = j;
}else if(map[i][j]==2){
targetX = i;
targetY = j;
}
}
}
System.out.println("begin:"+x);
System.out.println("end:"+y);
System.out.println("targetX:"+targetX);
System.out.println("targetY:"+targetY);
boolean[][] visit = new boolean[n][m];
this.dfs(map,x,y,targetX,targetY,visit);
System.out.println("result:"+result);
return (result==0?-1:result);
}
public static void main(String[] args) {
int[][] map = {{0,0,0,0,0},{0,0,0,-1,0},{0,0,-1,1,-1},{0,0,0,-1,0},{0,0,0,0,0},{0,0,0,0,0},{0,0,0,0,2}};
Visit visit = new Visit();
System.out.println(visit.countPath(map,map.length,map[0].length));
}
}