对于大二下才开算法课,内心其实是比较无感的,只是从大一开始已经浪费了一年半这才是最痛苦的。
算法刚讲完蛮力法,说是讲完,其实就是老师讲讲课件,布置一个实验题目,确实寥寥。
讲完蛮力法,就开始讲回溯法了。那作为组合问题中经典的八皇后问题自然是“首当其冲”了。
#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;
}