2024年寒假算法班集训day09-知识总结及题解(深搜下)

概念

DFS的高级应用包括解决复杂的搜索问题,如迷宫探索、图的所有路径搜索等。它与回溯法紧密相关,回溯法常用于需要试探和回退的搜索问题中,例如解决排列组合问题。DFS的另一个高级应用是在有向图中进行拓扑排序,这在解决依赖问题中特别有用,如任务调度。它也可以用来检测图中的环,这在确定图是否为有向无环图(DAG)时非常重要。在实现DFS时,特别注意避免重复访问已访问的节点,这通常需要额外的数据结构来跟踪每个节点的访问状态。

1、八皇后问题-2971

在这里插入图片描述
题目描述了经典的八皇后问题。在一个 (8 \times 8) 的国际象棋棋盘上,需要放置 8 个皇后,使得这些皇后互不攻击。在国际象棋中,皇后可以在水平、垂直和对角线方向上不限制步数地攻击。需要找到所有可能的摆放方法,并按照一定的格式输出。

输入描述:

无输入。

输出描述:

  • 按照规定的格式输出所有的八皇后摆放方法。每种摆放方法应该输出一个方案编号和一个 (8 \times 8) 的矩阵,矩阵中的 ‘1’ 表示皇后的位置,‘0’ 表示空格。

样例输出解释:

样例输出仅显示了所有解决方案中的前两个和最后一个。每种方案的输出格式为:

No.X
棋盘状态

其中,X 是方案的编号,棋盘状态由 8 行 8 列的 0 和 1 组成,1 表示皇后的位置。

代码解析:

代码中使用了回溯算法来解决八皇后问题。定义了一个二维数组 mp 来存储皇后的位置,以及三个一维数组 b, c, d 分别用于标记列、左对角线和右对角线上是否已放置了皇后。

void dfs(int i){
   
    // ...
}

dfs 函数是深度优先搜索的实现,用于逐行尝试放置皇后。如果在第 (i) 行找到一个合适的位置放置皇后,就更新 mp 和标记数组,然后递归地调用 dfs 函数尝试在下一行放置皇后。当所有皇后都被成功放置时,调用 print 函数输出当前方案。

性能考量:

由于问题的规模固定为一个 (8 \times 8) 的棋盘,算法的时间复杂度是可接受的。虽然可能的摆放方式有 (8!) 种,但由于皇后的攻击范围和回溯的使用,实际搜索的空间要小得多。

示例输出解释:

对于八皇后问题,程序将找出所有不同的摆放方案,并按顺序输出每一种方案。每种方案都包括一个方案编号和一个展示皇后位置的 (8 \times 8) 棋盘。

#include<iostream>
using namespace std;
int mp[9][9]={
   };//存储皇后位置
int b[9],c[16],d[17];//b:列 c:左对角线 d:右对角线
int ans=0;//放置皇后的方法数
void print(){
   
	ans++;//总方法数累加1
	cout<<"No."<<ans<<endl;
	for(int i=1;i<=8;i++){
   
		for(int j=1;j<=8;j++){
   
			cout<<mp[i][j];
		}
		cout<<endl;
	}
}
void dfs(int i){
   //第i行开始
	if(i==9){
   //搜索到第9行时,说明前8行放置完毕
		print();//自定义输出函数,输出该放置方案
		return ;
	}
	for(int j=1;j<=8;j++){
   //循环第i行所有列
		if(b[j]==0&&c[i-j+8]==0&&d[i+j]==0){
   
			mp[i][j]=1;//放置皇后
			//标识行、列、左对角线、右对角线不能再放置皇后
			b[j]=c[i-j+8]=d[i+j]=1;
			dfs(i+1);//下一行
			mp[i][j]=0;//清空第i行,第j列皇后
			b[j]=c[i-j+8]=d[i+j]=0;//清空皇后攻击范围
		}
	}
}
int main(){
   
	dfs(1);//第一行开始放置皇后
	return 0;
}

2、N皇后的判断-2972

在这里插入图片描述
这个问题是著名的 N 皇后问题的变体。目标是将 (n) 个皇后放在 (n \times n) 的棋盘上,使得没有两个皇后可以互相攻击。在国际象棋中,皇后可以在水平、垂直和对角线方向上不限制步数地攻击。

输入描述:

  • 输入包含一个整数 (n),表示有 (n) 个皇后需要放置。

输出描述:

  • 如果没有解决方案,输出 “NO”。
  • 否则,输出所有可能的解决方案。每个解决方案输出一个 “No.X”(X 是方案编号),后跟 (n \times n) 的棋盘状态。在棋盘状态中,‘1’ 表示皇后的位置,‘0’ 表示空位。

样例输入输出解释:

例如,对于样例输入 2,输出 “NO”,因为在 (2 \times 2) 的棋盘上无法放置 2 个皇后使它们互不攻击。

对于输入 4,输出两种解决方案,如样例输出所示。

代码解析:

定义了一个二维数组 mp 用于存储皇后的位置,以及三个一维数组 b, c, d 分别用于标记列、左对角线和右对角线上是否已放置了皇后。

void dfs(int i){
   
    // ...
}

dfs 函数是深度优先搜索的实现,用于逐行尝试放置皇后。如果在第 (i) 行找到一个合适的位置放置皇后,就更新 mp 和标记数组,然后递归地调用 dfs 函数尝试在下一行放置皇后。当所有皇后都被成功放置时,调用 print 函数输出当前方案。

性能考量:

由于问题的规模为 (n \times n),算法的时间复杂度取决于 (n) 的大小。对于较小的 (n)(如 (n \leq 10)),该算法是有效的。深度优先搜索加上适当的剪枝可以在可接受的时间内找到所有解决方案。

示例输出解释:

对于给定的 (n),程序将执行深度优先搜索,并找出所有不同的摆放方案,并按顺序输出每一种方案。每种方案都包括一个方案编号和一个展示皇后位置的 (n \times n) 棋盘。

#include<iostream>
using namespace std;
int mp[11][11]={
   };//存储皇后位置
int b[11],c[22],d[23];//b:列 c:左对角线 d:右对角线
int n,ans=0;//放置皇后的方法数
void print(){
   
	ans++;//总方法数累加1
	cout<<"No."<<ans<<endl;
	for(int i=1;i<=n;i++){
   
		for(int j=1;j<=n;j++){
   
			cout<<mp[i][j];
		}
		cout<<endl;
	}
}
void dfs(
  • 23
    点赞
  • 28
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值