【基础算法笔记】DFS(排列数字和n-皇后问题)

在acwing(一个很不错的算法学习平台)学习算法与数据结构,有时候一些题目要花费很长时间去想,下面写写我在学习过程中的思考和心得。也不知道能不能坚持写下去。自己的想法难免有不准确的地方,这里欢迎各位大佬指正。 


DFS

原题链接:排列数字 - AcWing

                  n-皇后问题 - AcWing

最关键是要理解回溯与恢复原状态的两个操作。

回溯:可以想象有一颗递归树,每次生成一个符合题意的结果后或者该情况不符合题意,就会返回到它的上一个节点。

恢复原状态:设置一个状态数组st[N],用来表示该位置是否可以存放值。0代表可以存放,1代表不能存放。每一次回溯过后都要执行恢复的操作。

排列数字

#include <iostream>
#include <cstring>
#include <algorithm>

using namespace std;
const int N = 10000;
int p[N], st[N], n;
void dfs(int u)
{
    if(u == n)
    {
        for (int i = 0; i < n; i ++ ) cout<<p[i]<<' ';
        cout<<endl;
        return;
    }
    
    for(int i = 1; i <= n; i ++)
    {
        if(st[i] == 0)
        {
            p[u] = i;
            st[i] = 1;
            dfs(u+1);  //进行递归树的下一层
            st[i] = 0; //回溯到上一个节点,要恢复到原状态
        }
    }
}

int main()
{
    cin>>n;
    dfs(0);
    return 0;
}

n-皇后问题:

n-皇后问题本质上就是排列数字的问题,有点抽象,用文字不好解释,直接上草图。然后就是解决如何表示对角线的问题了,我们可以把n*n矩阵抽象成一个平面坐标系,同一条对角线一定会过同一个b (y=x+b)。所以我们可以用截距b来表示对角线。

#include <iostream>
#include <cstring>
#include <algorithm>

using namespace std;
const int N = 20;
int col[N], dg[N], udg[N], n, x;
char p[N][N];
// col列:记录该列的使用状态
   dg对角线,udg反对角线:记录该条对角线的使用状态
   0表示未被使用
// p[N][N]用来存结果

void dfs(int u)
{
    if( u == n) //此时已经搜索了n行,输出结果
    {
        for (int i = 0; i < n; i ++ ) cout<<p[i]<<endl;
        cout<<endl;
        return;
    }
        
    int x = u;  //搜索u这一行
    for(int y = 0; y < n; y ++) //搜索列
    {
        //判断该位置能否放置'Q',0表示未被使用
        if(col[y] == 0 && dg[y + x] == 0 && udg[y - x + n] == 0)
        {
            p[x][y] = 'Q';
            col[y] = dg[y+x] = udg[y-x+n] = 1;  //更新位置状态
            dfs(x + 1);  //搜索下一行
            p[x][y] = '.';  //恢复原状态
            col[y] = dg[y+x] = udg[y-x+n] = 0;          
        }
    }
        
}
int main()
{
    cin>>n;
    for (int i = 0; i < n; i ++ )
        for (int j = 0; j < n; j ++ )
            p[i][j] = '.';
    dfs(0);
}

猜你喜欢

转载自blog.csdn.net/Radein/article/details/134587518