c++实现八皇后 回溯法+递归

对于大二下才开算法课,内心其实是比较无感的,只是从大一开始已经浪费了一年半这才是最痛苦的。

算法刚讲完蛮力法,说是讲完,其实就是老师讲讲课件,布置一个实验题目,确实寥寥。

讲完蛮力法,就开始讲回溯法了。那作为组合问题中经典的八皇后问题自然是“首当其冲”了。


#include<iostream>
#include<cmath>
using namespace std;

/*
1. 用一个一维数组来表示八皇后的摆放情况
   x[i]表示第i个皇后放在第i行的第x[i]列
2.剪枝条件
  不同行    每一行放一个皇后
  不同列    x[i] != x[j]
  不同斜线  |i - j| != |x[i] - x[j]|  即 abs(i - j) != abs(x[i] - x[j])
*/

int num;  //皇后的个数
int *x;   //数组x[num+1]
int sum;  //八皇后解的个数

bool check(int k){  //用来判断是否要进行剪枝
    for(int j=1;j<k;j++){
        if( abs(k - j) == abs(x[k] - x[j]) || x[j] == x[k] )  //判断条件
            return false;   //如果同列同斜线 则返回false
    }
    return true;
}

void backtrack(int t){
    if(t > num){   //num是皇后的数目
        sum++;   //sum用来统计有多少种解法
        for(int m=1; m<=num; m++){
            cout<<"<"<<m<<","<<x[m]<<">";  //输出当递归到八叉树的叶节点的时候的一个可行解
        }
        cout<<endl;
    }
    else{
        for(int i=1; i<=num; i++){
            x[t] = i;  //t从1开始 也就是第一行 第一个皇后
            if( check(t) ){
                backtrack(t+1);  //如果check函数返回为true,即判断成立 则进入下一行 下一级递归
            }
        }
    }
}

int main(){
    num = 8;
    sum = 0;
    x = new int [num+1];
    for(int i=0; i<=num; i++){
        x[i] = 0;
    }
    backtrack(1);
    cout<<"方案共有"<<sum<<"种"<<endl;
    delete []x;
}
 
 

另外,在csdn中找资料的时候,偶然点进去一个“十行代码解决八皇后问题”的帖子,觉得自己真的是太弱了。

#include <iostream>
int sum,ans[8];
int solve(int n, long long mark, int *ans){
	for (int i=n>8?++sum&0:0; n>8&&i<8; i!=7?std::cout << ans[i++] << " " : std::cout << ans[i++] << std::endl);
	for (int i=0; i<8; !(mark>>i&1)&&!(mark>>(n+i+7)&1)&&!(mark>>(n-i+30)&1)?solve(n+(ans[n-1]=i+1)-i, mark|1ll<<i|1ll<<(n+i+7)|1ll<<(n-i+30), ans):0,i++);
	return sum;}
int main(){
	std::cout << solve(1, 0, ans) << std::endl;
}

猜你喜欢

转载自blog.csdn.net/qq_41815015/article/details/79716176