八皇后问题

来源:互联网 发布:往届生银行知乎 编辑:程序博客网 时间:2024/06/10 22:21

方案一

  说的有点夸装,实际上并不只是八行代码,加上前面的变量声明之类的一共有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 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

原创粉丝点击