思路:箭靶上的数字代表的是经过的次数,我们用深度搜索每搜索一个点就标记这个点,并且
把对应列和行的次数减一,出口用一个方法判断,当到达(N,N)并且次数完全用尽时
返回true。
注意:下一个可以走的点一定是未被走过的,剩余次数大于0 的,因为最后要输出路径,所以把路
径记录到一个集合中去,在回溯的时候,不仅要取消标记,还要把用过的次数加回来,最重
要的是记录的路径也要删除。
import java.util.ArrayList;
import java.util.Scanner;
public class Main {
static int[][] vis;
static int N;
static int[] north;
static int[] west;
static ArrayList<Integer> sb=new ArrayList<>();
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
N = sc.nextInt();
vis = new int[N + 1][N + 1];
north = new int[N + 1];
west = new int[N + 1];
for (int i = 1; i <= N; i++) {
north[i] = sc.nextInt();
}
for (int i = 1; i <= N; i++) {
west[i] = sc.nextInt();
}
dfs(1,1);
}
public static void dfs(int row,int col){
if (row==N&&col==N){
west[row]--;
north[col]--;
if (judge()) {
sb.add((N - 1) * row + col - 1);
//打印
for (int i = 0; i < sb.size(); i++) {
System.out.print(sb.get(i) + " ");
}
System.out.println();
sb.remove(sb.size() - 1);
}
west[row]++;
north[row]++;
return ;
}
//向左走
if (col-1>0&&north[col-1]>0&&west[row]>1&&vis[row][col-1]!=1){
vis[row][col]=1;
sb.add(N*(row-1)+col-1);
north[col]--;
west[row]--;
dfs(row,col-1);
north[col]++;
west[row]++;
sb.remove(sb.size()-1);
vis[row][col]=0;
}
//向右走
if (col+1<=N&&north[col+1]>0&&west[row]>1&&vis[row][col+1]!=1){
vis[row][col]=1;
sb.add(N*(row-1)+col-1);
north[col]--;
west[row]--;
dfs(row,col+1);
north[col]++;
west[row]++;
sb.remove(sb.size()-1);
vis[row][col]=0;
}
//向下走
if (row+1<=N&&north[col]>1&&west[row+1]>0&&vis[row+1][col]!=1){
vis[row][col]=1;
sb.add(N*(row-1)+col-1);
north[col]--;
west[row]--;
dfs(row+1,col);
north[col]++;
west[row]++;
sb.remove(sb.size()-1);
vis[row][col]=0;
}
//向上走
if (row-1>0&&north[col]>1&&west[row-1]>0&&vis[row-1][col]!=1){
vis[row][col]=1;
sb.add(N*(row-1)+col-1);
north[col]--;
west[row]--;
dfs(row-1,col);
north[col]++;
west[row]++;
sb.remove(sb.size()-1);
vis[row][col]=0;
}
}
public static boolean judge(){
for (int i = 1; i <=N; i++) {
if (north[i]>0){
return false;
}
if (west[i]>0){
return false;
}
}
return true;
}
}