您的位置:首页 > 编程语言 > C语言/C++

C++解决八皇后问题

2012-12-01 13:44 274 查看
近日,因老师布置的一道题目才知道有八皇后这个问题,首先介绍一下八皇后问题吧。

八皇后问题:

设法在国际象棋的棋盘上放置八个皇后,使得其中任何一个皇后所处的“行”、“列”以及“对角线”上都不能有其它的皇后。

国际象棋棋盘其实就是一个8*8的方格子组成的,我们可以看成是8*8的数组。

我最初的想法是利用结构体,构造皇后这么一个结构,它有 row(行) 和 line(列) 俩个数据.然后在 main 主方法中先创建一个全为0的8*8数组(即棋盘)。

接着,分析题目可知,每一列必定有一个皇后,即这八个皇后必定分布在第一列....到第八列。然后利用循环遍历每一列,若发现某一个位置为0,则将皇后放入,并按照题目要求,对该位置所处的行和列级对角线均赋值1;直到找到第八个皇后。然而看似简单,其实仔细一想,要是找到第7个了,但是第8个没位置了怎么办?!

嗯,我想了一会儿,那撤销对第7个皇后的操作(之前赋值了1,现在必须重新赋值0),然后另找第7个的位置(因为第7个皇后的位置不唯一(可能哈)),但是可能会出现,所有第7个皇后的位置找遍了,8的位置还是不能确定,那么又得重新确定第6个皇后的位置.......总而言之就是当遇到某个皇后找不到合适位置时,必须回溯到前一个皇后,改变它的位置,如果还是无法确定,必须回溯到前前一个皇后.......想着想着逻辑就乱了。



嗯,烦的慌,玩会儿神庙逃亡再说........(半个小时后)....

貌似可以这样.....

每个皇后的位置只有八种可能(行确定,列待定),如第一个皇后只可能出现在:第一行第一列,第一行第二列......第一行第八列。所以8个皇后就有 8的8次方 种可能。只要她们俩俩之间满足一定的关系,就可以得出解决方案~~!!然后怒码代码!

#include "stdafx.h"
#include <iostream>

using namespace std;

//判断是否得出结果
bool judgeGetResult(int* a,const int large);

int main(int argc, char* argv[])
{
int count = 0;	//计数结果个数
int num_Row[8]; //皇后的列位置
for(int row_1 = 0;row_1 < 8;row_1++)			//在第一行,从第一列遍历到第八列
{
num_Row[0] = row_1;							//记下第一行皇后的列位置
for(int row_2 = 0;row_2 < 8;row_2++)		//在第二行,从第一列遍历到第八列,以下递推
{
num_Row[1] = row_2;						//记下第二行皇后的列位置,以下递推
for(int row_3 = 0;row_3 < 8;row_3++)
{
num_Row[2] = row_3;
for(int row_4 = 0;row_4 < 8;row_4++)
{
num_Row[3] = row_4;
for(int row_5 = 0;row_5 < 8;row_5++)
{
num_Row[4] = row_5;
for(int row_6 = 0;row_6 < 8;row_6++)
{
num_Row[5] = row_6;
for(int row_7 = 0;row_7 < 8;row_7++)
{
num_Row[6] = row_7;
for(int row_8 = 0;row_8 < 8;row_8++)
{
num_Row[7] = row_8;
if(judgeGetResult(num_Row,8))	//得出结果,并输出到屏幕上
{
cout<<"得出结果:"<<endl;
for(int i = 0;i< 8;i++)
cout<<"皇后"<<i+1<<"  "<<"("<<i+1<<","<<num_Row[i]<<")"<<endl;
count++;
}
}
}
}
}
}
}
}
}
cout<<"最后有 "<<count<<" 个解决方案";
return 0;
}

bool judgeGetResult(int* a,const int large)
{
for(int i = 0; i < large;i++)
for(int j = i+1;j < large;j++)
if(a[i] == a[j] || (a[i] - a[j]) == (i - j) || (a[i] - a[j]) == (j - i))//判断 俩俩 皇后之间是否满足八皇后问题的要求(就是我说的满足一定的关系)
return false;	//不满足
return true;	//满足
}

这种方法比较暴力,它验证了所有的可能(一些不需要验证的可能它也验证了,造成了效率的降低)并对每种可能进行了 28 次比较,所以运行时间会有些漫长,甚至在命令行里放不下所有的结果(最后有92种结果,如果把换行符endl去掉的话,就可以解决)。不过它能保证得出全面的正确的结果。不会漏解。

更高效的方法还有很多,大家可以google。我只是把我知道的分享给大家而已,毕竟出来混,总是要还的。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: