[经典算法] 八皇后

题目说明:

西洋棋中的皇后可以直线前进,吃掉遇到的所有棋子,如果棋盘上有八个皇后,则这八个皇后如何相安无事的放置在棋盘上,1970年
与1971年,E.W.Dijkstra与N.Wirth曾经用这个问题来讲解程式设计之技巧。

 

题目解析:

关于棋盘的问题,都可以用递回求解,然而如何减少递回的次数?在八个皇后的问题中,不必要所有的格子都检查过,例如若某列检查
过,该该列的其它格子就不用再检查了,这个方法称为分支修剪。

 

程序代码:

#include<iostream>
using namespace std;

const int N_SIZE = 8;

/// 使用数组记录状态
int UpperOblique[2*N_SIZE + 1] = {0};
int LowerOblique[2*N_SIZE + 1] = {0};
int Column[N_SIZE + 1] = {0};
int Queen[N_SIZE + 1] = {0};
int Number = 0;

void ShowResult()
{
    cout << "\nNO " << ++Number << ":" <<endl;
    for (int i=1; i<=N_SIZE; ++i)
    {
        for (int j=1; j<=N_SIZE; ++j)
        {
            if (Queen[i]==j)
            {
                cout << "Q";
            }
            else
            {
                cout << " .";
            }
        }
        cout << endl;
    }
}

void BlackTrack(int i)
{
    if (i > N_SIZE)
        ShowResult();
    else
    {
        for (int j=1; j<=N_SIZE; ++j)
        {
            if (Column[j]==0 &&
                UpperOblique[i-j+N_SIZE]==0 &&
                LowerOblique[i+j]==0)
            {
                Queen[i] = j;
                Column[j] = UpperOblique[i-j+N_SIZE]=LowerOblique[i+j]=1;
                BlackTrack(i+1);
                Column[j] = UpperOblique[i-j+N_SIZE]=LowerOblique[i+j]=0;
            }
        }
    }
}

int main()
{
    BlackTrack(1);
    return 0;
}

 

#include <iostream>
#include <stdlib.h>

using namespace std;

const int N_SIZE = 8;
int   Record[N_SIZE+1] = {0}; /// 记录每列选择的位置
int   ResultNum = 0;

bool  Check(int x)
{
    for (int i = 1; i<x; i++)
    {
        if ((Record[i]==Record[x]) ||
             (abs(Record[i]-Record[x]) == abs(i-x)))
        {
            return false;
        }
    }

    return true;
}

void  ShowResult()
{
    cout << "No. " << ++ResultNum <<endl;
    for (int i=1; i<=N_SIZE; ++i)
    {
        for (int j=1; j<=N_SIZE; ++j)
        {
            if (Record[i]==j)
            {
                cout << "1 ";
            }
            else
            {
                cout << "0 ";
            }
        }
        cout << endl;
    }
}

void  BackTrack(int x)
{
    if (x > N_SIZE)
    {
        ShowResult();
    }
    else
    {
        for (int j=1; j <=N_SIZE; ++j)
        {
            Record[x] = j;
            if (Check(x))
            {
                BackTrack(x+1);
            }
        }
    }
}

int main()
{
    BackTrack(1);
    return 0;
}

还有诸如 遗传算法、退火算法、位运算和基于Q一矩阵的快速搜索算法。但是这些算法中,遗传算法和基于Q一矩阵的快速搜索算法一般只能得到部分解;退火算法得到的解往往是近似解,存在一定的误差:位运算依赖硬件,32位机器只能计算32皇后,如果要计算任意皇后,需要增加变量,会带来额外的系统开销和编程难度。

posted @ 2015-08-07 13:27  Quincy  阅读(2585)  评论(0编辑  收藏  举报