时限:1000ms 内存限制:10000K 总时限:3000ms
描述
输出8皇后问题所有结果。
输入
没有输入。
输出
每个结果第一行是No n:的形式,n表示输出的是第几个结果;下面8行,每行8个字符,‘A’表示皇后,‘.’表示空格。不同的结果中,先输出第一个皇后位置靠前的结果;第一个皇后位置相同,先输出第二个皇后位置靠前的结果;依次类推。
输入样例
输出样例
输出的前几行:
No 1:
A…….
….A…
…….A
…..A..
..A…..
……A.
.A……
…A….
No 2:
A…….
…..A..
…….A
..A…..
……A.
…A….
.A……
….A…
程序如下:
#include <iostream>
#include <cstdlib>
using namespace std;
int a[8]={0};
int sum=0;
void print()
{
int i,j;
cout<<"No "<<sum<<":"<<endl;
for(i=0;i<8;i++)
{
for(j=0;j<8;j++)
{
if(a[i]==j)
cout<<'A';
else
cout<<'.';
}
cout<<endl;
}
}
int canplace(int row,int col)
{
int i;
for(i=0;i<row;i++)
{
if(a[i]==col||abs(i-row)==abs(a[i]-col))
return 0;
}
return 1;
}
void search(int m)
{
if(m==8)
{
sum++;
print();
}
else
{ int i;
for(i=0;i<8;i++)
{
a[m]=i;
if(canplace(m,i))
{
search(m+1);
}
}
}
}
int main()
{
search(0);
return 0;
}
void search(int m)
{
if(m==8)
{
sum++;
print();
}
else
{ int i;
for(i=0;i<8;i++)
{
a[m]=i;
if(canplace(m,i))
{
search(m+1);
}
}
}
}
算法是逐行安排皇后的,其参数m为现在正执行到第几行。8是皇后数.
第2行好理解,如果程序当前能正常执行到第8行,那自然是找到了一种解法,于是八皇后问题解法数加1。
如果当前还没排到第八行,则进入else语句。遍历所有列col,将当前col存储在数组a里,然后使用canplace()检查row行col列能不能摆皇后,若能摆皇后,则递归调用search去安排下一列摆皇后的问题。
还不太清楚?再慢点来,刚开始的时候row=0,意思是要对第0行摆皇后了。
If判断失败,进入else,进入for循环,col初始化为0
显然,0行0列的位置一定可以摆皇后的,因为这是第一个皇后啊,后宫空荡她想怎么折腾就怎么折腾,于是canplace(0,0)测试成功,递归调用search(1)安排第1行的皇后问题。
第1行时row=1,进来if依然测试失败,进入for循环,col初始化为0。1行0列显然是不能摆皇后的,因为0行0列已经有一个圣母皇太后在那搁着了,于是canplace()测试失败,循环什么也不做空转一圈,col变为1。1行1列依然canplace()测试失败,一直到1行2列,发现可以摆皇后,于是继续递归search(2)去安排第二个皇后位置。
如果在某种情况下问题无解呢?例如前面在4皇后问题中,0行0列摆皇后是无解的。假设前面递归到search(2)时候,发现第2行没有地方可以摆皇后,那怎么办呢?要注意search(2)的调用是在search(1)的for循环框架内的,search(2)若无解,则自然而然search(1)的for循环col自加1,即将第1行的皇后从1行2列改为1行3列的位置,检查可否放皇后后继续安排下一行的皇后。如此递归,当search(0)的col自加到7,说明第一列的皇后已经遍历了从0行1列到0行7列,此时for循环结束,程序退出。
在主函数中调用search(0),得到正确结果,8皇后问题一共有92种解法。