【八皇后问题:白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;
}
浙公网安备 33010602011771号