题目链接:https://www.lanqiao.cn/problems/89/learning/
题目描述:
数据规模:
题目思路:数据规模较小,可以用深搜暴力求解,其实这个就是 dfs 迷宫问题的变形,我们从迷宫的入口(左上角)开始搜索,直到走到迷宫的出口(右上角)停止。不过在这里会多了几个约束,比如每次走到一个新格子,需要向 北面的墙 和 西面的墙 射箭,只有当走到迷宫时,在两面的墙射箭的数量等于题目给定的值,才算解决了这个问题。还有一个问题就是在这一过程我们要不断维护一个路径(从入口到出口)。
写代码遇到的几个细节:
- 在搜索到匹配的值时,直接就输出答案,不然在dfs退栈时会把完整的答案破坏,除非在回溯时加上判断标志。
- 记得剪枝操作,如果在某一面的墙的箭 > 大于题目给定的数值,那么就没必要搜索下去,因为接着搜索下去只会让值更大。
- 在遇到迷宫出口时,不需要对其做额外的回溯处理,因为这个已经包含在了dfs的主体中了。
import java.util.ArrayList;import java.util.List;import java.util.Scanner;// 1:无需package// 2: 类名必须Main, 不可修改public class Main {static int n;static int[][] map;static int[] north1, west1;static int[] north2, west2;static boolean[][] visited;static int[][] dirs = {{-1, 0}, {0, 1}, {1, 0}, {0, -1}};static List<Integer> ans = new ArrayList<>();static boolean is_end = false;static boolean judge(){for(int i = 0; i < n; i++){if(west1[i] != west2[i]){return false;}if(north1[i] != north2[i]){return false;}}return true;}static void dfs(int row, int col){if(row == n-1 && col == n-1){if(judge()){for(int i = 0; i < ans.size(); i++){if(i != ans.size()-1)System.out.printf(ans.get(i) + " ");elseSystem.out.printf(ans.get(i) + "\n");}is_end = true;}return;}if(is_end){return;}if(west2[row] > west1[row] || north2[col] > north1[col]){return;}//向四个方向进行搜索for(int i = 0; i < 4; i++){int newRow = row + dirs[i][0];int newCol = col + dirs[i][1];if(newRow < 0 || newRow >= n || newCol < 0 || newCol >= n){continue;}if(!visited[newRow][newCol]){visited[newRow][newCol] = true;ans.add(map[newRow][newCol]);north2[newCol]++;west2[newRow]++;dfs(newRow, newCol);visited[newRow][newCol] = false;ans.remove(Integer.valueOf(map[newRow][newCol]));north2[newCol]--;west2[newRow]--;}}}public static void main(String[] args) {Scanner scan = new Scanner(System.in);n = scan.nextInt();north1 = new int[n];west1 = new int[n];north2 = new int[n];west2 = new int[n];for(int i = 0; i < n; i++){north1[i] = scan.nextInt();}for (int i = 0; i < n; i++){west1[i] = scan.nextInt();}map = new int[n][n];visited = new boolean[n][n];int num = 0;for(int i = 0; i < n; i++){for(int j = 0; j < n; j++){map[i][j] = num++;}}//深搜前的初始化visited[0][0] = true;ans.add(0);west2[0]++;north2[0]++;dfs(0, 0);//0 4 5 1 2 3 7 11 10 9 13 14 15}}
