Acwing排列数字、n皇后问题 java实现
DFS 深度优先搜索
递归和DFS不要区分的太开 这思想上都是交融的
树与图的存储
树是一种特殊的图,与图的存储方式相同。
对于无向图中的边ab,存储两条有向边a->b, b->a。
因此我们可以只考虑有向图的存储。
(1) 邻接矩阵:g[a][b] 存储边a->b
(2) 邻接表:
// 对于每个点k,开一个单链表,存储k所有可以走到的点。h[k]存储这个单链表的头结点
int h[N], e[N], ne[N], idx;
// 添加一条边a->b
void add(int a, int b)
{
e[idx] = b, ne[idx] = h[a], h[a] = idx ++ ;
}
// 初始化
idx = 0;
memset(h, -1, sizeof h);
一、排列数字
给定一个整数 n,将数字 1∼n 排成一排,将会有很多种排列方法。
现在,请你按照字典序将所有的排列方法输出。
输入格式
共一行,包含一个整数 n。
输出格式
按字典序输出所有排列方案,每个方案占一行。
数据范围
1≤n≤7
输入样例:
3
输出样例:
1 2 3
1 3 2
2 1 3
2 3 1
3 1 2
3 2 1
1.题解
代码如下(示例):
import java.util.Scanner;
public class Main{
static int N = 10;
static int[] p = new int[N];
static boolean[] st = new boolean[N];
static int n ;//全局变量的初始值是0 , 局部变量的初始值可以是任意值
// 计算u->n的所经过的路径path
static void dfs(int u)
{
// 边界条件
if (u == n)
{
for (int i = 0; i < n; i++) {
System.out.println(p[i]);
}
return;
}
else
{
for (int i = 1; i <= n; i++)
{
if (!st[i])
{
path[u] = i;
st[i] = true;
dfs(u+1); // 回溯之后, 要恢复现场
path[u] = 0;
st[i] = false;
}
}
}
}
public static void main(String [] args){
Scanner san = new Scanner(System.in);
n = san.nextInt();
dfs(0);
}
}
插入C++的代码块 这个是Y总的 state二进制表示 boolean值
#include <iostream>
using namespace std;
const int N = 10;
int n;
int path[N];
void dfs(int u, int state)
{
if (u == n)
{
for (int i = 0; i < n; i ++ ) printf("%d ", path[i]);
puts("");
return;
}
for (int i = 0; i < n; i ++ )
if (!(state >> i & 1))//位运算 表示state的第i位不为1
{
path[u] = i + 1;
dfs(u + 1, state + (1 << i));//改变第i位的状态 让它变为1
}
}
int main()
{
scanf("%d", &n);
dfs(0, 0);
return 0;
}
2、n皇后问题
输入格式
共一行,包含整数 n。
输出格式
每个解决方案占 n 行,每行输出一个长度为 n 的字符串,用来表示完整的棋盘状态。
其中 . 表示某一个位置的方格状态为空,Q 表示某一个位置的方格上摆着皇后。
每个方案输出完成后,输出一个空行。
注意:行末不能有多余空格。
输出方案的顺序任意,只要不重复且没有遗漏即可。
数据范围
1≤n≤9
输入样例:
4
输出样例:
.Q…
…Q
Q…
…Q.
…Q.
Q…
…Q
.Q…
2.2 题解
col[x],dg[y - x + n],udg[x + y]分别记录的是该位置的列,斜,反斜线上
y = x + b
y = -x + b
导出b 因为怕y-x为负数 所以加上了n
代码如下(示例):
import java.util.Scanner;
public class Main{
static int N = 20;
static char[][] g = new char[N][N];
static boolean[] col = new boolean[N];
static boolean[] dg = new boolean[N];//正斜
static boolean[] udg = new boolean[N];//反斜
//按行递归
static void dfs(int y,int n)
{
if(y == n)
{
for (int i = 0; i < n; i ++ )
{
for (int j = 0; j < n; j ++ )
System.out.println(g[i][j]);
System.out.println();
}
System.out.println();
return;
}
for(int x = 0;x < n;x++)
{
if(!col[x] && !dg[y - x + n] && !udg[x + y])
{
g[y][x] = 'Q';
col[x] = dg[y - x + n] = udg[x + y] = true;
dfs(y + 1,n);
col[x] = dg[y - x + n] = udg[x + y] = false;
g[y][x] = '.';
}
}
}
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);
int n = scan.nextInt();
for (int i = 0; i < n; i ++ )
for (int j = 0; j < n; j ++ )
g[i][j] = '.';
dfs(0,n);
}
}
总结
主要讲了dfs的两道题 dfs如何搜索 以后讲如何遍历 用到递归dfs 和bfs如何使用
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享4款.NET开源、免费、实用的商城系统
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
· 上周热点回顾(2.24-3.2)