(1) 深度优先遍历 —— 模板题 AcWing 846. 树的重心(层序遍历,用到了回溯+剪枝,深搜没有一个常用的框架)
int dfs(int u)
{
st[u] = true; // st[u] 表示点u已经被遍历过
for (int i = h[u]; i != -1; i = ne[i])
{
int j = e[i];
if (!st[j]) dfs(j);
}
}
(2) 宽度优先遍历 —— 模板题 AcWing 847. 图中点的层次(最短路,宽搜有一个最常用的框架)
queue<int> q;
st[1] = true; // 表示1号点已经被遍历过
q.push(1);
while (q.size())
{
int t = q.front();
q.pop();
for (int i = h[t]; i != -1; i = ne[i])
{
int j = e[i];
if (!s[j])
{
st[j] = true; // 表示点j已经被遍历过
q.push(j);
}
}
}
例子:
对123排列组合:
package com.huawei.it.acwing;
import java.io.IOException;
public class Main {
private static final int n = 3;
private static final int[] path = new int[10];
private static final boolean[] st = new boolean[10];
public static void main(String[] args) throws IOException {
dfs(0);
}
private static void dfs(int u) {
if (u == n) {
for (int i = 0; i < n; i++) {
System.out.print(path[i]);
}
System.out.println();
return;
}
for (int i = 1; i <= n; i++) {
if (!st[i]) {
path[u] = i;
st[i] = true;
dfs(u + 1);
st[i] = false;
}
}
}
}
n皇后问题
方法一:
package com.huawei.it.acwing;
public class Main {
private static final int n = 4;
private static final int N = 20;
private static final char[][] g = new char[N][N];
private static final boolean[] col = new boolean[N];
private static final boolean[] dg = new boolean[N];
private static final boolean[] udg = new boolean[N];
public static void main(String[] args) {
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
g[i][j] = '.';
}
}
dfs(0);
}
private 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;
}
// 枚举第u行皇后放在哪一列,正对角线:b=u+i,反对角线:b=-u+i+n,u就是x,i就是y
for (int i = 1; i <= n; i++) {
if (!col[i] && !dg[u + i] && !udg[n - u + i]) {
g[u][i] = 'Q';
col[i] = dg[u + i] = udg[n - u + i] = true;
dfs(u + 1);
col[i] = dg[u + i] = udg[n - u + i] = false;
g[u][i] = '.';
}
}
}
}
方法二:
package com.huawei.it.acwing;
public class Main {
private static final int n = 4;
private static final int N = 20;
private static final char[][] g = new char[N][N];
private static final boolean[] row = new boolean[N];
private static final boolean[] col = new boolean[N];
private static final boolean[] dg = new boolean[N];
private static final boolean[] udg = new boolean[N];
public static void main(String[] args) {
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
g[i][j] = '.';
}
}
dfs(0, 0, 0);
}
private 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] && !col[y] && !dg[x + y] && !udg[x - y + n]) {
g[x][y] = 'Q';
row[x] = col[y] = dg[x + y] = udg[x - y + n] = true;
dfs(x, y + 1, s + 1);
row[x] = col[y] = dg[x + y] = udg[x - y + n] = false;
g[x][y] = '.';
}
}
}
BFS:
在一个n*m的二维数组里走迷宫,0表示可以走,1表示不可以走。从左上角(1,1)走到右下角(n,m),问至少需要移动多少次。
基本框架:
queue<——初始
while(queue不空) {
t<——队头
扩展t
}
package com.huawei.it.acwing;
import java.util.LinkedList;
import java.util.Queue;
import java.util.Scanner;
/*
走迷宫样例::
5
4
0 0 0 0
1 1 0 1
0 0 0 0
0 1 1 1
0 0 0 0
*/
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
int m = sc.nextInt();
int[][] Maze = new int[n][m]; //迷宫
int[][] dist = new int[n][m]; //记录该该位置到入口的最短距离
//迷宫初始化
for (int i = 0; i < n; i++) {
for (int j = 0; j < m; j++) {
Maze[i][j] = sc.nextInt();
dist[i][j] = -1;
}
}
int[] start = new int[] {0, 0};//起点坐标
int[][] directions = new int[][] {{-1, 0}, {0, 1}, {1, 0}, {0, -1}};//四个方向
dist[0][0] = 0;//起点距离
//宽搜(BFS)找到最短路径
Queue<int[]> queue = new LinkedList<>();
queue.add(start);
while (!queue.isEmpty()) {
int[] temp = queue.poll();
for (int[] direction : directions) {
int x = temp[0] + direction[0];
int y = temp[1] + direction[1];
if (x >= 0 && x < n && y >= 0 && y < m && Maze[x][y] == 0 && dist[x][y] == -1) {
dist[x][y] = dist[temp[0]][temp[1]] + 1;
queue.add(new int[] {x, y});
System.out.println("(" + x + "," + y + ")");
}
}
}
System.out.println(dist[n - 1][m - 1]);
sc.close();
}
}