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