学习搜索与回溯
搜索与回溯
,是递归的一种重要形式,只要学好回溯,我们就能在一些类似于求方案数、走迷宫类的题目
我们只要学会了回溯,就好比站在了递归这个巨人的肩膀上
搜索与回溯
学会了结构,就可以横跨“递归”大道
这是结构↓↓↓
C++:
#include<iostream> using namespace std; void dfs(int k){//层数 if(达到目的) 输出(或者方案数+1) else{ for(遍历所有的算符){ if(没有用到){ 标记 dfs(k+1)//下一层递归 回溯 } } } }
Python:
def dfs(k): global ans#方案数 if(达到目的) :输出或ans+=1 else: for i in 所有的算符: if(没有用到): 标记 dfs(k+1)#递归下一层 回溯
JavaScript:
function dfs(k){ if(达到目的)输出或ans+1 else{ for(遍历所有的算符){ if(没有用到){ 标记 dfs(k+1) 回溯 } } } }
样例题目
题目描述
在一个nXn的国际象棋棋盘上放置n(n<=12)个皇后,使它们不能互相攻击(即任意两个皇后不能在同一行、同一列或同一对角线上)。试求出所有方法。
输入输出格式
输入
输入一个数n .(n<=12)
输出
输出所有的排列方案总数。
输入输出样例
输入
4
输出
2
本题思路
注意事项:
·1、需要用到深搜
格式
·2、可以用一维数组(列表)来表示每个王后所放的位置,k层递归就是第k行
·3、判断是否放置合法:
1、斜着放合法:行列是否差值相等,如:|x1-x2|==|y1-y2|
2、列数放合法:遍历所有放过的Ai不相等
3、同行放合法:不可能不合法,因为递归层数就是行数
·4、如果层数(行数)> N 则方案数+1(调试时可以输出每次放的地方)并结束此次函数执行(return)
·5、记住了就可以写代码了 😉😉😃😃
代码模块
我们可以先简单的进行一个模板,简单的输入输出,最后解决dfs
部分
C++
#include<iostream> #include<cmath> using namespace std; int n,ans,a[13]; void ba(int k){ if(k>n){ ans++; return; }else{ for(int j=1;j<=n;j++){ int bk=0; for(int i=1;i<k;i++){ if((a[i]==j)||(abs(k-i)==abs(j-a[i]))){ bk=1; break; } } if(!bk){ a[k]=j; ba(k+1); a[k]=0; } } } } int main() { cin>>n; ba(1); cout<<ans; return 0; }
Python:
ans = 0 n = int(input()) a = [] def dfs(k): global ans,n,a if k == n: ans+=1 return for j in range(0,n):# 选列 flag=True for i in range(0,k): if a[i]==j or abs(i-k)==abs(a[i]-j): flag=False break if flag: a.append(j) dfs(k+1) a.pop() dfs(0) print(ans)
JS:
这个可以自己转,跟这两个语言的代码差不多,因为我有些不会
能不能点个赞再走 😉 😃