深度搜索是一个求多步骤最佳解的一个最实用的方法,其原理来自与树,树的每个节点都有子节点(最末端不算)那么相当于多种选择,通过条件选择一个又一个节点产生出不同情况,再根据最后的出口条件就可以得到最佳解了。(本人蒻楉大佬有问题请指教)
dfs实现的是一个递归条件所以其开头是从问题的开始位置开始递归每次得到满足条件,标记赋值后就往下递归,最后再回溯成初始条件方便第一次往后继续判断是否还有更优解
dfs(初始条件)
{
判断条件出口
for循环查找满足条件的位置并标记赋值然后递归,递归结束再回溯
}
本蒻楉因为只会最基本的深搜模板所以再遇到最精典的八皇后问题就卡住了qwq
现在理解了一写大佬的思想在这里分享一下八皇后问题的解法思路
1问题关键是找到没有占用的点的位置
2考虑其对角线和列还有行
因为我们是按照行往下递归所以行不做考虑,列的话用一个bool型存起来,对角线问题可以观察其对角线上的关系比如从左下到右上的对角线的关系是行和列之和相同,从左上到右下的对角线的关系是
行和列之差相同,不同的对角线其和或者差不同而且唯一(正负也计算在内),所以用一个数组代表左下到右上的对角线,再范围内尽可能大最好是2n+1个单位也可以防止溢出,用其和不同来区分每个左下到右上对角线的不同,用另外一个数组代表左上到右下的对角线,由于其差不同但是用行减列可能会出现为负的情况所以这个时候用行-列+n来区分左上到右下的对角线确保其每条线都不同。
可根据这些条件来解决八皇后问题下面是AC代码
#include<iostream>
using namespace std;
int n;//n*n棋盘
bool visit[100];
bool b[100];
bool c[100];
int a[15];//代表每种的排列
int sum = 0;//总的情况数
void dfs(int line)
{
if (line > n)
{
sum++;
if (sum > 3) return;
for (int i = 1; i <= n; i++)
{
cout << a[i] << " ";
}
cout << endl;
}
for (int i = 1; i <= n; i++)
{
if (!visit[i] && !b[i + line] && !c[line-i + n])
{
visit[i] = 1;
b[i + line] = 1;
c[line-i + n] = 1;
a[line] = i;
dfs(line + 1);
b[i + line] = 0;
c[line-i + n] = 0;
visit[i] = 0;
}
}
}
int main()
{
cin >> n;
dfs(1);
cout << sum << endl;
system("pause");
return 0;
}
回溯条件可以有多种比如涉及到多个问题需要有保留和判断是否使用过可以吧visit设置成int型来做到以上几点,深搜一定需要回溯,回溯的时候要瞻前顾后检查是否全部重置,最终条件要写在前面,根据题意来写。
本蒟蒻还会继续更新这篇博客只要遇到了问题会及时更新,各位路过的大佬欢迎指点qaq.