主要思考顺序来遍历搜索(暴力搜索)=> 递归。
排列数字:https://www.acwing.com/problem/content/844/
如:追溯到倒数第二个节点(A点),标记为已使用,然后再往下找,到叶子节点(标记、输出),回溯到上一节点,取消叶子的标记,然后再回溯到上一节点,取消A点的标记,当前表示 i = 2 这个节点已经遍历,接着遍历 i= 3 这个节点。
import java.io.*;
import java.util.Scanner;
public class Main{
public static BufferedWriter log = new BufferedWriter(new OutputStreamWriter(System.out));
public static int N = 10;
public static int number[] = new int[N];
public static boolean st[] = new boolean[N];
public static void dfs(int u)throws IOException{
if(u == N){
for(int i = 0; i < N; i++)
log.write(number[i]+" ");
log.write("\n");
log.flush();
}
for(int i = 1; i <= N; i++){
if(!st[i]){
number[u] = i;
st[i] = true;
dfs(u + 1);
st[i] = false;
}
}
}
public static void main(String[] args)throws IOException{
Scanner in = new Scanner(System.in);
N = in.nextInt();
dfs(0);
}
}
皇后问题的两种解法
第一种枚举每一列,递归到下一层(下一层又去枚举每一列)。
第二种从左到右依次枚举每一个列,直到这列的末尾绕后跳到下一层首行。
第一种速度快。
import java.io.*;
import java.util.Scanner;
public class Main{
public static int N = 20;
public static char g[][] = new char[N][N];//存储找到的方案
public static boolean clo[] = new boolean[N];//存储这一列是否被使用
public static boolean dg[] = new boolean[N];//存储正对角线是否被使用
public static boolean udg[] = new boolean[N];//存储反对角线是否被使用
public static void dfs(int u){
if(u == N){
for(int i = 0; i < N; i++){
for(int j = 0; j < N; j++)
System.out.print(g[i][j]);
System.out.println();
}
System.out.println();
return;
}
for(int i = 0; i < N; i++){
if(!clo[i] && !dg[i + u] && !udg[i - u + N]){
g[i][u] = 'Q';
clo[i] = dg[i + u] = udg[i - u + N] = true;
dfs(u + 1);
clo[i] = dg[i + u] = udg[i - u + N] = false;
g[i][u] = '.';
}
}
}
public static void main(String []args){
Scanner in = new Scanner(System.in);
N = in.nextInt();
for(int i = 0; i < N; i++)
for(int j = 0; j < N; j++)
g[i][j] = '.';
dfs(0);
}
}
import java.util.Scanner;
public class Main{
public static int N = 20;
public static char g[][] = new char[N][N];//存储找到的方案
public static boolean clo[] = new boolean[N];//存储这一行是否被使用
public static boolean row[] = new boolean[N];//存储这一列是否被使用
public static boolean dg[] = new boolean[N];//存储正对角线是否被使用
public static boolean udg[] = new boolean[N];//存储反对角线是否被使用
public static void dfs(int x, int y, int s){
if(y == N){//表示列到了末尾,跳到下一行首位
y = 0;
x++;
}
if(x == N){//到达最后一行切所有皇后排列完成
if(s == N){
for(int i = 0; i < N; i++){
for(int j = 0; j < N; j++) System.out.print(g[i][j]);
System.out.println();
}
System.out.println();
}
return;
}
//不放皇后
dfs(x, y + 1, s);
//放皇后
if (!row[x] && !clo[y] && !dg[x + y] && !udg[x - y + N]){
row[x] = clo[y] = dg[x + y] = udg[x - y + N] = true;
g[x][y] = 'Q';
dfs(x, y + 1, s + 1);
g[x][y] = '.';
row[x] = clo[y] = dg[x + y] = udg[x - y + N] = false;
}
}
public static void main(String []args){
Scanner in = new Scanner(System.in);
N = in.nextInt();
for(int i = 0; i < N; i++)
for(int j = 0; j < N; j++)
g[i][j] = '.';
dfs(0, 0, 0);
}
}