紫书第七章-----暴力求解法(回溯法---八皇后问题)

八皇后问题 OpenJ_Bailian – 2698

【回溯法思想】

参考《妙趣横生的算法》杨峰

回溯法的基本思想是:在包含问题的所有解的解空间树中,按照深度优先搜素的策略,从根结点出发深度搜索解空间树。当搜索到某一结点时,要先判断该结点是否包含问题的解,如果包含,就从该结点出发继续搜索下去;如果该结点不包含问题的解,那就说明以该结点为根的子树一定不包含问题的最终解,因此要跳过对该结点为根的子树的系统探索,逐层向其祖先结点回溯。这个过程叫做解空间树的“剪枝”操作。

以四皇后问题为例,可以逐行放皇后,也可以逐列放皇后,我们以逐行放皇后为例。用数组Q[4][4]记录整个棋盘。每行放置皇后的位置用列下标表示,则四皇后问题可以大致描述一下。第一行可以放置的位置(列下标)是:0,1,2,3,以第一行放置在0为例,第二行可以放置在2,3,再以第二行放置在2为例,第三行无处可放,说明第二行放置在2位置导致问题最终也不会有解,那就回溯到第二行(剪枝),把2位置改为不放置皇后,继续试探第二行的3位置,再进行深搜。

【按列放置皇后的AC代码】

#include<iostream>

using namespace std;

int a[8][8]={0};
int cnt=0;

void print(){
    cout<<"No. "<<++cnt<<endl;
    for(int i=0;i<8;i++){
        for(int j=0;j<8;j++)
            cout<<a[i][j]<<" ";
        cout<<endl;
    }
}
//由于是按列放置的,就不需要判断右上方和右下方了
bool check(int row,int col){
    for(int t=0;t<8;t++){if(a[row][t]) return false;}//判断行
    for(int t=0;t<8;t++){if(a[t][col]) return false;}//判断列
    for(int s=row-1,t=col-1;s>=0 && t>=0;s--,t--){if(a[s][t]) return false;}//判断左上方
    for(int s=row+1,t=col-1;s<8 && t>=0;s++,t--){if(a[s][t]) return false;}//判断左下方
    return true;
}

void dfs(int col){
    if(col==8) {print();}
    for(int row=0;row<8;row++){
        if(check(row,col)){
            a[row][col]=1;
            dfs(col+1);
            a[row][col]=0;//回溯剪枝,继续
        }
    }
}

int main()
{
    dfs(0);
    return 0;
}
    原文作者:回溯法
    原文地址: https://blog.csdn.net/ccnuacmhdu/article/details/79247138
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞