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

八皇后问题

2017-08-11 20:25 218 查看

方案一

  说的有点夸装,实际上并不只是八行代码,加上前面的变量声明之类的一共有40多行的样子吧,好像是
在知乎上看到的,现在有时间再把它写下来:
  其中用到了一些c++11特性,例如lambda 以及给予范围的 for循环。
  其他的没什么好说的,看代码,上面也有注释的。



1 #include <iostream>
2 #include <algorithm>
3 #include <vector>
4 #include <set>
5 using namespace std;
6 void eightQueen(int n);
7 int main()
8 {
9     eightQueen(8);
10     system("pause");
11     return 0;
12 }
13
14 void eightQueen(int n)
15 {
16     int count = 0;
17     vector<int> border(n);
18     for (int i = 0; i < n; ++i)
19         border[i] = i + 1;    //这一步就决定了每一行的上下左右都不会有其他的皇后
20     vector<int> afterAdd(8);
21     vector<int> afterSub(8);
22     for(;;){
23         transform(border.begin(), border.end(), afterAdd.begin(),
24             [](int i)->int{static int index = 1; i += index; index++; return i; });
25         transform(border.begin(), border.end(), afterSub.begin(),
26             [](int i)->int{static int index = 1; i -= index; index++; return i; });
27         set<int> afterAddSet(afterAdd.begin(), afterAdd.end());
28         set<int> afterSubSet(afterSub.begin(), afterSub.end());
29         if (afterAddSet.size() == 8 && afterSubSet.size() == 8){    //如果斜对角线上都没有元素话
30             ++count;
31             for (auto c : border)
32                 cout << c << ' ';
33             cout << endl;
34         }
35         if (!next_permutation(border.begin(), border.end())){
36             cout << "Total : " << count << endl;
37             break;
38         }
39     }
40 }




嗯大概就是这样,下面是结果:



1 5 8 6 3 7 2 4
1 6 8 3 7 4 2 5
1 7 4 6 8 2 5 3
1 7 5 8 2 4 6 3
2 4 6 8 3 1 7 5
2 5 7 1 3 8 6 4
2 5 7 4 1 8 6 3
2 6 1 7 4 8 3 5
2 6 8 3 1 4 7 5
2 7 3 6 8 5 1 4
2 7 5 8 1 4 6 3
2 8 6 1 3 5 7 4
3 1 7 5 8 2 4 6
3 5 2 8 1 7 4 6
3 5 2 8 6 4 7 1
3 5 7 1 4 2 8 6
3 5 8 4 1 7 2 6
3 6 2 5 8 1 7 4
3 6 2 7 1 4 8 5
3 6 2 7 5 1 8 4
3 6 4 1 8 5 7 2
3 6 4 2 8 5 7 1
3 6 8 1 4 7 5 2
3 6 8 1 5 7 2 4
3 6 8 2 4 1 7 5
3 7 2 8 5 1 4 6
3 7 2 8 6 4 1 5
3 8 4 7 1 6 2 5
4 1 5 8 2 7 3 6
4 1 5 8 6 3 7 2
4 2 5 8 6 1 3 7
4 2 7 3 6 8 1 5
4 2 7 3 6 8 5 1
4 2 7 5 1 8 6 3
4 2 8 5 7 1 3 6
4 2 8 6 1 3 5 7
4 6 1 5 2 8 3 7
4 6 8 2 7 1 3 5
4 6 8 3 1 7 5 2
4 7 1 8 5 2 6 3
4 7 3 8 2 5 1 6
4 7 5 2 6 1 3 8
4 7 5 3 1 6 8 2
4 8 1 3 6 2 7 5
4 8 1 5 7 2 6 3
4 8 5 3 1 7 2 6
5 1 4 6 8 2 7 3
5 1 8 4 2 7 3 6
5 1 8 6 3 7
e795
2 4
5 2 4 6 8 3 1 7
5 2 4 7 3 8 6 1
5 2 6 1 7 4 8 3
5 2 8 1 4 7 3 6
5 3 1 6 8 2 4 7
5 3 1 7 2 8 6 4
5 3 8 4 7 1 6 2
5 7 1 3 8 6 4 2
5 7 1 4 2 8 6 3
5 7 2 4 8 1 3 6
5 7 2 6 3 1 4 8
5 7 2 6 3 1 8 4
5 7 4 1 3 8 6 2
5 8 4 1 3 6 2 7
5 8 4 1 7 2 6 3
6 1 5 2 8 3 7 4
6 2 7 1 3 5 8 4
6 2 7 1 4 8 5 3
6 3 1 7 5 8 2 4
6 3 1 8 4 2 7 5
6 3 1 8 5 2 4 7
6 3 5 7 1 4 2 8
6 3 5 8 1 4 2 7
6 3 7 2 4 8 1 5
6 3 7 2 8 5 1 4
6 3 7 4 1 8 2 5
6 4 1 5 8 2 7 3
6 4 2 8 5 7 1 3
6 4 7 1 3 5 2 8
6 4 7 1 8 2 5 3
6 8 2 4 1 7 5 3
7 1 3 8 6 4 2 5
7 2 4 1 8 5 3 6
7 2 6 3 1 4 8 5
7 3 1 6 8 5 2 4
7 3 8 2 5 1 6 4
7 4 2 5 8 1 3 6
7 4 2 8 6 1 3 5
7 5 3 1 6 8 2 4
8 2 4 1 7 5 3 6
8 2 5 3 1 7 4 6
8 3 1 6 2 5 7 4
8 4 1 3 6 2 7 5
Total : 92




一共有92种方式,由于是枚举了所有的可能情况,所以用时稍微有一点长。

http://www.cnblogs.com/-wang-cheng/p/4854484.html

###方案二

1问题描述

N皇后问题,就是如何将国际象棋中的N个皇后放在N*N的棋盘上而不会互相攻击,是一种通过枚举,再递归、回溯的思想。

2思路

以8皇后问题为例,可知在8*8二维数组中,每个点用data[i][j]表示(0 <= i,j <= 7)。

其中其主对角线上(左上到右下)的每个点的i-j+7的值都相同(范围0-14)。

其从对角线上(右上到左下)的每个点i+j的值都相同(返回0-14)。

且其中每个子方阵的主对角线之间的i-j+7的值都不同,从对角线之间的i+j的值也不同。

如在4*4的子方阵中的data[3][4]:

穿过data[3][4]的主对角线:3-4+7=6

穿过data[3][4]的从对角线:3+4=7

若是穿过data[4][4],其主对角线:4-4+7=7;从对角线:4+4=8

为何要研究这种规律呢?

因为摆放皇后时,可知N个皇后肯定在不同行,不同列,以及不同对角线上。因此每在一个不同行摆放一个皇后时,首先要检查该列是不是被占用,以及穿过该点的主、从对角线是否被占用,若是则要换列。

3具体代码

bool checkCol[]:表示每一列的占用情况,大小1*N

bool leftCross[]:表示穿过该放置点(i,j)的主对角线的占用情况,其下标为i-j+7。

bool rightCross[]:表示穿过该放置点(i,j)的从对角线的占用情况,下标为i+j。

int * *data:N*N棋盘。

#include <iostream>
#include <stdlib.h>
#include <stdio.h>
using namespace std;

int count_Method = 0;
int queenNum = 0;
bool *checkCol;
bool *leftCross;
bool *rightCross;
int **data;

void getNQueens( int );

/*
功能: 求解放置8皇后方案的个数。
输入:N个皇后个数
无
返回:
int:放置8皇后方案的个数
*/

int PlaceQueenMethodNum(int N)
{
/*在这里实现功能*/
queenNum = N;
data = (int **)malloc(N*sizeof(int*));
for(int i = 0; i < N; i++){
data[i] = (int *)malloc(N*sizeof(int));
}
checkCol = (bool *)malloc(N*sizeof(bool));   //column(列)占用情况,占用为true,反之false
leftCross = (bool *)malloc((2*N-1)*sizeof(bool));//左对角线
rightCross = (bool *)malloc((2*N-1)*sizeof(bool));//右对角线情况
for(int i = 0; i < 2*N-1; i++ ) //主、从对角线
leftCross[i] = rightCross[i] = false; //表示安全

for(int i = 0; i < N; i++ )//chess
{
checkCol[i] = false;
for(int j = 0; j < N; j++ ){
data[i][j] = 0;
}
}

getNQueens( 0 );

return count_Method;
}

void getNQueens( int row )
{
if( row == queenNum )//N个皇后安置就位,解决方案+1
{
count_Method++;
return;
}

for( int column = 0; column < queenNum; column++ )
{
if( !checkCol[column] && leftCross[row-column+7] == false && rightCross[row+column] == false )
{
data[row][column] = 1;
//安置皇后
checkCol[column] = true;   //此列被占
leftCross[row-column+7] = true; //主对角线被占
rightCross[row+column] = true;  //从对角线被占
getNQueens(row+1); //下一个皇后
//此步重置,列右移继续找
data[row][column] = 0;
checkCol[column] = false;
leftCross[row-column+7] = false;
rightCross[row+column] = false;
}
}
}

int main(){
int n;
cin>>n;
cout<<PlaceQueenMethodNum(n);
system("pause");
}


http://blog.csdn.net/chenloxiaoea/article/details/50246523
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  八皇后 c语言