zoukankan      html  css  js  c++  java
  • [经典算法] 八皇后

    题目说明:

    西洋棋中的皇后可以直线前进,吃掉遇到的所有棋子,如果棋盘上有八个皇后,则这八个皇后如何相安无事的放置在棋盘上,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 << "
    NO " << ++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皇后,如果要计算任意皇后,需要增加变量,会带来额外的系统开销和编程难度。

  • 相关阅读:
    Luogu P1020 导弹拦截
    洛谷 p1196 带权并查集
    gradle 语法基础
    Codeforces Round #542 div.2 C
    我了解的字符编码
    洛谷p3374 树状数组1
    树状数组2
    线段树模板 求区间和, 区间加法,乘法更新
    洛谷 p1886 滑动窗口
    HDOJ.1251
  • 原文地址:https://www.cnblogs.com/Quincy/p/4710520.html
Copyright © 2011-2022 走看看