1. 八皇后问题介绍
要在8*8的国际象棋棋盘中放8个皇后,使任意两个皇后都不能互相吃掉。规则:皇后能吃掉同一行、同一列、同一对角线的任意棋子。求所有的解。
2.解决思想:
- 我们可以设8个皇后分别排在1,2,3,4,5,6,7,8行上。
- a[1],a[2].....a[8]的值分别表示每一行上的皇后位于第几列。。
- 要求每一个皇后不在同一行,这一要求已经在步骤1中默认达到。要求每一行的皇后不在同一列,同一对角线,可以使用两个for来实现,判断语句是
if ((a[i]==a[j])||(abs(a[i]-a[j])==i-j))
则说明不符合要求。
3.解决方法:
3.1暴力枚举法:
使用八重循环,遍历每一行所有的列,从中找出满足条件的解:
#include <iostream>
using namespace std;
bool check_1(int a[],int n)
{
for(int i=2;i<=n;i++) //要使用双重循环,因为每一行都要与前面所有行进行比较
{
for(int j=1;j<=i-1;j++)
{
if ((a[i]==a[j])||(abs(a[i]-a[j])==i-j))
{
return false;
}
}
}
return true;
}
void queens_1()
{
int a[9];
int count = 0;
for(a[1]=1;a[1]<=8;a[1]++)
{
for(a[2]=1;a[2]<=8;a[2]++)
{
for(a[3]=1;a[3]<=8;a[3]++)
{
for(a[4]=1;a[4]<=8;a[4]++)
{
for(a[5]=1;a[5]<=8;a[5]++)
{
for(a[6]=1;a[6]<=8;a[6]++)
{
for(a[7]=1;a[7]<=8;a[7]++)
{
for(a[8]=1;a[8]<=8;a[8]++)
{
if(!check_1(a,8))
continue;
else
{
for(int i=1;i<=8;i++)
{
cout<<a[i];
}
cout<<endl;
count++;
}
}
}
}
}
}
}
}
}
cout<<count<<endl;
}
void main()
{
queens_1();
}
3.2 递归方法
//因为在放置每一列每一行的皇后时,可能就已经不合法了,所以后续的递归并不需要,所以在每次递归放置一次皇后时都需要判断
//当前放置的皇后与之前放置的皇后是否合法
#include <bits/stdc++.h>
using namespace std;
const int maxn = 20;
int n,p[maxn],Count = 0; //p[i]代表第i列皇后的行号,count为摆放次数
void takequeen(int index) {
if(index == n+1){ //如果已经放置了n个皇后 //写递归先写返回条件
Count++;
return;
}
for(int row = 1;row <= n;row++){ //枚举每一列皇后可能放置的行号
bool flag = true;
for(int pre = 1;pre < index;pre++){ //枚举index之前的列
if(abs(index -pre) == abs(row - p[pre]) || row == p[pre]) { //如果当前列的皇后与之前列皇后在同一斜线或者在同一行上
flag = false;
break;
}
}
if(flag){
p[index] = row;
takequeen(index+1);
}
}
}
int main(void){
n = 8;
takequeen(1); //开始放第一列的皇后
cout<<Count<<endl;
return 0;
}