开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第1天,点击查看活动详情
DFS
深度优先搜索。以二叉树为例,只有当前节点不能继续遍历时,才会往回退,否则就继续搜索。 使用栈这种数据结构实现。空间复杂度为O(n)。不具有“最短路径”的性质。 把握两个概念:回溯、剪枝。DFS考虑顺序,类似递归,考虑dfs函数的意义。
全排列数字
使用dfs算法,使用path数组保存结果,使用used数组判断数字是否使用。明确每一层要做的事情:
- 判断当前数字是否使用,如果没有使用,就使用当前数字。
- 每次回溯时恢复原状态。
import java.util.Scanner;
public class Main {
static int N = 10;
//使用path保存全排列数。
static int path[];
static boolean used[];
static int n;
public static void main(String[] args) {
Scanner s = new Scanner (System.in);
n = s.nextInt();
path = new int [n];
used = new boolean [n + 1];
dfs(0);
}
static void dfs(int u) {
//如果u是n,说明当前已经排好了n个数字,输出即可。
if(u == n) {
for(int i = 0;i<n;i++) {
System.out.print(path[i] + " ");
}
System.out.println();
}
//寻找当前没有使用的数字。
for(int i = 1;i<=n;i++) {
//如果当前数字没有使用,则使用当前数字,继续深度搜索。
if(!used[i]) {
path[u] = i;
used[i] = true;
dfs(u + 1);
used[i] = false;
}
}
}
}
八皇后问题
解法一:类似全排列的思想。**按行进行dfs。**不用考虑同一行的问题。
import java.util.Scanner;
public class Main {
static int N = 20;
static char grp[][];
static int n;
static boolean col[] = new boolean [N];
static boolean dg[] = new boolean [N];
static boolean udg[] = new boolean [N];
public static void main(String[] args) {
Scanner s = new Scanner (System.in);
n = s.nextInt();
grp = new char [n][n];
for(int i = 0;i<n;i++) {
for(int j = 0;j<n;j++) {
grp[i][j] = '.';
}
}
dfs(0);
}
static void dfs(int row) {
if(row == n) {
for(int i = 0;i<n;i++) {
System.out.println(grp[i]);
}
System.out.println();
return;
}
//判断该行的每列位置是否合法。合法——不在同一列、同一斜线、同一直线。
for(int coll = 0;coll<n;coll++) {
//每一条对角线对应唯一截距:反对角线:y = x + b 截距:b = y - x
// 对角线:y = -x + b 截距:b = y + x
if(!col[coll] && !dg[row + coll] && !udg[n + coll - row]) {
grp[row][coll] = 'Q';
col[coll] = dg[row + coll] = udg[n + coll - row] = true;
dfs(row + 1);
grp[row][coll] = '.';
col[coll] = dg[row + coll] = udg[n + coll - row] = false;
}
}
}
}
解法二:把每一个格子都分为两种状态【放(满足条件时)/不放(不需要条件)】。 当满足x为最后的一行并且皇后数量等于n时,才会输出答案。
import java.util.Scanner;
public class Main {
static int N = 20;
static int n;
static char grp[][];
static boolean row [] = new boolean [N];
static boolean colum [] = new boolean [N];
static boolean bg [] = new boolean [N];
static boolean ubg [] = new boolean [N];
public static void main(String[] args) {
Scanner s = new Scanner (System.in);
n = s.nextInt();
grp = new char [n][n];
dfs(0,0,0);
}
static void dfs(int x,int y,int s) {
//当前行全部走了一遍,跳到下一行。
if(y == n) {
x ++;
y = 0;
}
//走到了最后一行
if(x == n) {
//此时的皇后数等于n的数量,即为符合条件
if(s == n) {
for(int i = 0;i<n;i++) {
System.out.println(grp[i]);
}
System.out.println();
}
return ;
}
//当前格子不放皇后
grp[x][y] = '.';
dfs(x,y + 1,s);
//当前格子放皇后
if(!row [x] && !colum[y] && !bg[x + y] && !ubg[n + x - y]) {
row[x] = colum[y] = bg[x + y] = ubg[n + x - y] = true;
grp[x][y] = 'Q';
dfs(x,y + 1,s + 1);
row[x] = colum[y] = bg[x + y] = ubg[n + x - y] = false;
grp[x][y] = '.';
}
}
}