每日一题(小白)回溯篇7
首先我们可以判断出这是一个dfs的题目,因为简言之就是要求最短路径。其次这个题目与直接找最短路径有所不同,增加了条件必须依次穿过指定的符号。无论坦克走到任何一点都有四个方向可以走(越界要判断),结束的条件是到达指定的终点。本题不难看出可以判断每次的步数,若已经大于目前的结果数据直接跳出循环(剪枝)。
①字符数组存储字符有
②接收起点x1,y1和终点x2,y2
③开始向前走
④判断结束条件,判断边界条件,判断是否已走过,判断交替条件
⑤如果满足条件,当前位置为true;进入递归
⑥回溯,退出循环
⑦剪枝
⑧调用函数输出结果
代码如下👇
static int n;static int result=(int)1e9;static char[][] c;static boolean[][] b= new boolean[110][110];static int x1,x2,y1,y2;static int[] dx= {0,-1,1,0};static int[] dy= {1,0,0,-1};//四个方向static int[][] arr=new int[1000][1000];//结果数组public static void dfs(int x,int y,int ans,char f) {if (ans>result) {return;}if (x==x2 && y==y2) {result=Math.min(ans, result);}for (int i = 0; i < 4; i++) {int x3=x+dx[i];int y3=y+dy[i];if (x3<1 || x3>n || y3<1 || y3>n) {continue;}if (b[x3][y3]) {continue;}if (c[x3][y3] == f) {continue;}b[x3][y3]=true;dfs(x3,y3,ans+1,c[x3][y3]);b[x3][y3]=false;//回溯精髓差点忘了}}public static void main(String[] args) {Scanner scan = new Scanner(System.in);n=scan.nextInt();scan.nextLine();c=new char[110][110];for (int i = 1; i <= n; i++) {String s=scan.nextLine();s=s.replaceAll(" ", "");for (int j = 0; j < n; j++) {c[i][j+1]=s.charAt(j);}}for (int i = 1; i <= n; i++) {for (int j = 1; j <= n; j++) {if (c[i][j]=='A') {x1=i;y1=j;}if (c[i][j]=='B') {x2=i;y2=j;}}}
// System.out.println(x1+" "+y1+" "+x2+" "+y2);
// for (int i = 1; i <= n; i++) {
// for (int j = 1; j <= n; j++) {
// System.out.print(c[i][j]);
// }
// System.out.println();
// }测试点dfs(x1,y1,0,'A');if (result!=(int)1e9) {System.out.println(result);}else {System.out.println(-1);}scan.close();}
下面为注释代码,如果理解不透可以参考👇
static int n;//给定大小static int result=(int)1e9;//最大值初始化结果static char[][] c;//雷区static boolean[][] b= new boolean[110][110];//雷区的复制 static int x1,x2,y1,y2;//起点终点static int[] dx= {0,-1,1,0};static int[] dy= {1,0,0,-1};//四个方向static int[][] arr=new int[1000][1000];//结果数组public static void dfs(int x,int y,int ans,char f) {if (ans>result) {//剪枝return;}if (x==x2 && y==y2) {//到达终点result=Math.min(ans, result);//保存最短的}for (int i = 0; i < 4; i++) {//向前走int x3=x+dx[i];int y3=y+dy[i];if (x3<1 || x3>n || y3<1 || y3>n) {//是否越界continue;}if (b[x3][y3]) {//是否走过continue;}if (c[x3][y3] == f) {//是否交替进入continue;}b[x3][y3]=true;//进入递归dfs(x3,y3,ans+1,c[x3][y3]);b[x3][y3]=false;//回溯精髓差点忘了}}public static void main(String[] args) {Scanner scan = new Scanner(System.in);n=scan.nextInt();scan.nextLine();c=new char[110][110];for (int i = 1; i <= n; i++) {//存储给定雷区String s=scan.nextLine();s=s.replaceAll(" ", "");for (int j = 0; j < n; j++) {c[i][j+1]=s.charAt(j);}}for (int i = 1; i <= n; i++) {//终点起点保存for (int j = 1; j <= n; j++) {if (c[i][j]=='A') {x1=i;y1=j;}if (c[i][j]=='B') {x2=i;y2=j;}}}dfs(x1,y1,0,'A');//调用if (result!=(int)1e9) {System.out.println(result);//输出结果}else {System.out.println(-1);//无结果输出-1}scan.close();}