【八皇后问题:白249页5.4】多重循环-递归-回溯-深搜(八皇后例题)
(1)什么时候用 多重循环,什么时候用递归
比如:当N=3时候,我们可以这样写
但是实际情况
递归
search(k)表示当前是第k重循环,也就是枚举第k个位置的选择 void search(int k) { for (int i=1; i<=N; i++) { a[k]=i; search(k+1); } }
递归 添加边界条件 if (k>N) { bool flag=true; for (int i=1; i<=N; i++) for (int j=i+1; j++; j<=N; j++) if (a[i]==a[j]) { //判断是否存在了相同的选择 flag=false; break; } return; }
回溯
不想在最后才判断是否重复选择 开一个bool数组chosen[],初始化全为false for (int i=1; i<=N; i++) if (!chosen[i]) { a[k]=i; chosen[i]=true; search(k+1); chosen[i]=false; }
(2)综合应用八皇后问题
#include<iostream> #include<iomanip> #include<cstdio> #include<cstdlib> using namespace std; bool b[100]; //b[j]=1 标记占领第j列的 bool d[100],c[100]; //c[i..j] d[i..j] 标记占领对角线 int sum,a[100]; //a[i]=j 表示第i行列摆放皇后。 int print() { int i; sum++; cout<<"sum="<<sum<<endl; for(int i=1;i<=8;i++) cout<<setw(4)<<a[i]; cout<<endl; } int search(int i) //标记行 { int j; //标记列 for(j=1;j<=8;j++) if((!b[j])&&(!c[i+j])&&(!d[i-j+7])) //结合行 两个对角线确定位置 { a[i]=j; //放置皇后位置 b[j]=1; //占领了第j列 c[i+j]=1; d[i-j+7]=1; //标记此时对角线不能占用。 if(i==8) print(); //如果全占打印 else search(i+1); b[j]=0; c[i+j]=0; d[i-j+7]=0; } } int main() { search(1); return 0; }