八皇后问题:
八皇后问题,是一个古老而著名的问题,是回溯算法的经典案例,该问题由国际西洋棋棋手马克斯▪贝瑟尔于1848年提出,在8×8格的国际象棋上摆放八个皇后,使其不能互相攻击,即任意两个皇后都不能处于同一行,同一列或者同一斜线上,问一共有多少种摆法;八皇后问题可以推广为更一般的n皇后的问题:这时棋盘的大小为n×n,而皇后的个数同样为n,当且仅当n=1或者n≧4是问题有解;
问题分析:
首先成功摆放皇后的条件是,使其在每一行都有一个皇后,而且任意两个皇后不处于同一行,同一列或者同一斜线;那么按照这个条件进行回溯法分析:
一:摆放棋盘需要考虑的情况:
1:同行/同列情况:假设皇后1的坐标为a(i,j),皇后2的坐标为a(m,n),则(i≠m || j≠n);
3:同一斜线情况:假设皇后1的坐标为a1(0,4),皇后2的坐标为a2(1,3),皇后3的坐标为a3(2,2),那么这三个皇后一定是同一斜线的(为了让大家更方便观察,特意从网上copy下一张图片:)
所以当两个皇后的x轴,y轴的坐标之和相等或者两个皇后的x轴,y轴的坐标之差的绝对值相等的时候,这两个皇后一定是在同一条斜线上;
二:回溯法摆放
当在摆放皇后位置的时候,如果发现在摆放第n个皇后的时候无论在这行怎么摆放都会与它之前的皇后发生冲突的时候,就需要掉头回到上一行,重新进行上一行的皇后摆放,如此类推下去,如果n为第一行的皇后,则摆放失败;
代码如下:
#include<iostream>
#include<cmath>
using namespace std;
#define N 8
int a[N];
int count=1;
int check(int n)
{
int i;
for(i=0;i<n;i++){
if(a[i]==a[n]||fabs(n-i)==fabs(a[i]-a[n])){
return 0;
}
}
return 1;
}
void show()
{
int i,x,y;
int f[N][N]={0};
cout<<"第"<<count++<<"组:";
for(i=0;i<N;i++){
f[i][a[i]]=1;
cout<<"("<<i<<","<<a[i]<<")"<<" ";
}
cout<<endl;
for(x=0;x<N;x++){
for(y=0;y<N;y++){
if(f[x][y]==1){
cout<<"●";
}else{
cout<<"○";
}
}
cout<<endl;
}
}
void put(int n)
{
int i;
if(n==N){
return ;
}
for(i=0;i<N;i++){
a[n]=i;
if(check(n)){
if(n==N-1){
show();
}else{
put(n+1);
}
}
}
}
int main()
{
put(0);
return 0;
}