回溯法
回溯法(探索与回溯法)是一种选优搜索法,又称为试探法,按选优条件向前搜索,以达到目标。但当探索到某一步时,发现原先选择并不优或达不到目标,就退回一步重新选择,这种走不通就退回再走的技术为回溯法,而满足回溯条件的某个状态的点称为“回溯点”。
回溯算法递归框架:
int a[n];
try(i)
{
If(i>n)
输出结果;
else
for(j=下界;j<=上界;j++){
if(满足约束条件){
标识占领资源(如a[i]置1)
If(满足限界)
try(i+1) //扩展下一个节点
清理所占资源 (如a[i]置0) //回溯
}
}
}
经典问题:八皇后
在8×8格的国际象棋上摆放8个皇后,使其不能互相攻击,即任意两个皇后都不能处于同一行、同一列或同一斜线上,问有多少种摆法。
#include<iostream>
using namespace std;
int b[40]={0},c[40]={0},d[40]={0},n,j; //n表示n位皇后
int num[40][40]={0};
int count=1;
void print()
{
printf("\n方案:%d\n",count++);
for(int x=1;x<=n;x++){
for(int y=1;y<=n;y++)
{
printf("%d",num[x][y]);
}
printf("\n");
}
printf("\n");
}
void quee(int i) //当前为第i个皇后
{
if(i==n+1)
print();
for (int j = 1; j <= n; j++) //遍历改行所有元素
if (b[j] == 0 && c[i + j] == 0 && d[i - j + n]==0) //判断行和左右对角线有没有被占领优美被占领
{
/*如果有条件则就将该位置占领*/
num[i][j]=1; //把第i行j列置1
b[j] = 1;
c[i + j] = 1;
d[i - j + n] = 1;
if (i <= n)
quee(i + 1); //继续开始下一行,如果这下一行
/*回溯*/
num[i][j]=0;
b[j] = 0;
c[i + j] = 0;
d[i - j + n] = 0;
}
}
int main() {
cout<<"请输入皇后的个数:"<<endl;
cin >> n;
quee(1);
return 0;
}