深搜

算法过程

void dfs(状态A)
  1. 判断当前的状态是否合法,合法则继续执行,否则回到上次调用
  2. 先走下一层,也就是调用dfs(A+变化量)

深搜其实就是一条路走到黑,走不通了再回头的方法

例一:将1,2,3,4,5全排列

思路:
1,可以使用n重for循环(暴力搜索法)
2,递归思想,转化为多个子问题

也就是说:先固定1,对2345全排列,下一步就是固定2,对345全排列,下一步就是固定3,对45全排列,再固定4,最后只剩下5,无法再继续。那么就回溯,回到上一步固定3的位置,对45全排列(12354),又无法再继续,再次回溯到固定2的位置,对345全排列......以此类推

具体做法

void dfs (固定前dep-1个数全排列,任务是把第dep个数放回)
1. dep>n则输出,返回
2. 否则从1~n循环
3. vis[]记录i是否用过,没用过就把i固定在当前位置并调用dfs(dep+1)//实现递归,固定前dep个数,任务是把第dep+1个数返回
4. 调用完dfs(dep+1)后把固定在当前位置的i拿走(清零,a[dep]=0)

代码

#include <iostream>

using namespace std;

int n=5;
int a[10] , vis[10];
void dfs(int dep)
{
	if(dep>5)
	{
		for(int i=1;i<=n;i++)
		   cout<<a[i]<<' ';
		cout<<endl;
		return;   
	}
	for(int i=1;i<=n;i++)
	{
		if(vis[i]) continue ;
		a[dep]=i;vis[i]=1;
		dfs(dep+1);
		a[dep]=0;vis[i]=0;
	}
}
int main ()
{
	dfs(1);
	return 0;
}

例二:n皇后

n皇后问题是指将 n 个皇后放在 n×n 的国际象棋棋盘上,使得皇后不能相互攻击到,即任意两个皇后都不能处于同一行、同一列或同一斜线上

现在给定整数 n
,请你输出所有的满足条件的棋子摆法。

输入格式

共一行,包含整数 n

输出格式

每个解决方案占 n 行,每行输出一个长度为 n 的字符串,用来表示完整的棋盘状态。
其中 . 表示某一个位置的方格状态为空,Q 表示某一个位置的方格上摆着皇后。
每个方案输出完成后,输出一个空行。
注意:行末不能有多余空格。
输出方案的顺序任意,只要不重复且没有遗漏即可。

数据范围

1≤n≤9

输入样例:

4

输出样例:

.Q..
...Q
Q...
..Q.

..Q.
Q...
...Q
.Q..

思路

题目的意思是在每一行放一个皇后,并且互相不在各自位置的对角线和列上。

1.首先将位置表示为二维数组g[N][N],初始全部存放为 . 放了皇后之后再更新为 Q
2.每放一次皇后就将这些不能放的位置标记起来
(col表示列,zd表示主对角线,fd表示副对角线),false 表示不能放,true表示可以放,每次放置就相当于将子问题递归,也就是dfs(dep+1), 然后清零...

可以找到规律:主对角线上的点满足y-x是定值副对角线上的点满足y+x是定值(同时由于y-x会出现负值,那么就在后面·+n ,保证zd[]里的值都为正)

代码

#include <iostream>
using namespace std;
const int N = 20; 

// bool数组用来判断搜索的下一个位置是否可行
// col列,zd对角线,fd反对角线
// g[N][N]用来存路径

int n;
char g[N][N];
bool col[N], zd[N], fd[N];

void dfs(int dep) {
    // dep == n 表示已经搜了n行,故输出这条路径
    if (dep == n) {
        for (int i = 0; i < n; i ++ ) cout << g[i] << endl;
        puts("");  // 换行
    }

    // 枚举dep这一行,搜索合法的列
    int x = dep;
    for (int y = 0; y < n; y ++ )    // 剪枝(对于不满足要求的点,不再继续往下搜索)  
        if (col[y] == false && zd[y - x + n] == false && fd[y + x] == false) 
        {
            col[y] = zd[y - x + n] = fd[y + x] = true;
            g[x][y] = 'Q';
            dfs(dep + 1);
            g[x][y] = '.';  // 恢复现场
            col[y] = zd[y - x + n] = fd[y + x] = false;
        }
}

int main() {
    cin >> n;
    for (int i = 0; i < n; i ++ )
        for (int j = 0; j < n; j ++ )
            g[i][j] = '.';

    dfs(0);

    return 0;
}   

posted @ 2023-02-01 01:05  wustRen  阅读(67)  评论(0)    收藏  举报