[經典算法] 八皇后


題目說明:

西洋棋中的皇后可以直線前進,吃掉遇到的所有棋子,如果棋盤上有八個皇后,則這八個皇后如何相安無事的放置在棋盤上,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皇后,如果要計算任意皇后,需要增加變量,會帶來額外的系統開銷和編程難度。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM