zoukankan      html  css  js  c++  java
  • 【算法学习】八皇后问题 递归算法

    递归算法

     1 package com.test.spring.mytag;
     2 
     3 public class Queen {
     4     // 皇后个数
     5     static int SIZE = 8;
     6     // 一共有多少种解法
     7     static int count = 0;
     8     // 表示解的数组,比如queen[0]=0,表示解的第0行第0列放置了皇后,如果使用二维数组,内存占用将会是一维数组的N倍
     9     static int queen[] = new int[SIZE];
    10 
    11     /**
    12      * 检查第row行第queen[row]列是否可以放置queen,以下三种情况之一不能放置queen
    13      * 1.其他行的queen[row]列不能放置queen,即queen[i]不能等于queen[row]
    14      * 2.queen[row]所在位置的主对角线不能放置queen,主对角线元素的特征是横坐标减去纵坐标所得的结果相同
    15      * 3.queen[row]所在位置的副队角线不能防止queen,副对角线元素的特征是横坐标加上纵坐标所得的结果相同
    16      */
    17     static boolean check(int row) {
    18         for (int i = 0; i < queen.length && i != row; i++) {
    19             if (queen[i] == queen[row] || i - queen[i] == row - queen[row] || i + queen[i] == row + queen[row]) {
    20                 return false;
    21             }
    22         }
    23         return true;
    24     }
    25 
    26     // 处理第row行
    27     static void process(int row) {
    28         if (row == SIZE) {
    29             show();
    30             count++;
    31         } else {
    32             for (int column = 0; column < queen.length; column++) {
    33                 queen[row] = column;
    34                 if(check(row)) {
    35                     process(row+1);
    36                 }
    37             }
    38         }
    39     }
    40 
    41     static void queen() {
    42         process(0);
    43     }
    44 
    45     static void show() {
    46         System.out.println("***********************");
    47         for (int i = 0; i < 8; i++) {
    48             for (int j = 0; j < 8; j++) {
    49                 if (queen[i] == j) {
    50                     System.out.print(" Q ");
    51                 } else {
    52                     System.out.print(" . ");
    53                 }
    54             }
    55             System.out.println();
    56         }
    57         System.out.println("***********************");
    58     }
    59 
    60     public static void main(String[] args) {
    61         queen();
    62         System.out.println(count);
    63     }
    64 }

     程序第34行,只考虑了检查通过的情况,没有在检查失败之后进行queen[row] = 0以重置检查失败的行,这是因为check函数的循环条件,即第18行的

    i < queen.length && i != row

     已经限定了,即每一行只考虑是否兼容于其之前的那些行,不需要考虑后面的行,当然这个条件其实应该改一下,改成 i < row就可以了

    c++版,可以看到解的运算过程

    #include<iostream>
    #include<windows.h>
    using std::cin;
    using std::cout;
    using std::endl;
    
    class Queen
    {
    private:
        //皇后个数
        const int SIZE = 8;
        //表示解的数组,比如queen[0]=0,表示解的第0行第0列放置了皇后,如果使用二维数组,内存占用将会是一维数组的N倍
        int queen[8] = { 0 };
        //尝试次数
        int tried = 1;
        //解的个数
        int count = 0;
        
    public:
        //直观展示皇后的放置情况,row代表当前处理到第几行,只是为了debug方便
        void show(int row)
        {
            Sleep(1000);
            system("cls");
            cout << "row: " << row << " column: " << queen[row] << endl;
            cout << "tried: " << tried << endl;
            cout <<    "found: " << count << endl;
            for (size_t row = 0; row < SIZE; row++)
            {
                for (size_t column = 0; column < SIZE; column++)
                {
                    if (queen[row] == column)
                    {
                        cout << " Q ";
                    }
                    else
                    {
                        cout << " . ";
                    }
                }
                cout << endl;
            }
        }
    
        /**
        * 检查第row行第queen[row]列是否可以放置queen,以下三种情况之一不能放置queen
        * 1.其他行的queen[row]列不能放置queen,即queen[i]不能等于queen[row]
        * 2.queen[row]所在位置的主对角线不能放置queen,主对角线元素的特征是横坐标减去纵坐标所得的结果相同
        * 3.queen[row]所在位置的副队角线不能防止queen,副对角线元素的特征是横坐标加上纵坐标所得的结果相同
        */
        bool check(int row)
        {
            tried++;
            show(row);
            for (int i = 0; i < SIZE && i != row; i++)
            {
                if (queen[i] == queen[row] || i - queen[i] == row - queen[row] || i + queen[i] == row + queen[row])
                {
                    return false;
                }
            }
            return true;
        }
    
        //处理第row行
        void process(int row)
        {
            if (row == SIZE)
            {
                count++;
                cout << "按回车继续寻找下一个解" << endl;
                if (cin.get() != '
    ')
                {
                    return;
                }
            }
            else
            {
                for (size_t column = 0; column < SIZE; column++)
                {
                    queen[row] = column;
                    if (check(row))
                    {
                        process(row + 1);
                    }
                    /*else
                    {
                        queen[row] = 0;
                    }*/
                }
            }
        }
    
        void start()
        {
            process(0);
            cout << "一共有 " << count << " 个解" << endl;
        }
    };
    
    
    
    int main(void)
    {
        Queen queen;
        queen.start();
        system("pause");
        return 0;
    }
  • 相关阅读:
    c++ ShellExecuteEx调用java打包的exe程序
    麻省理工学院公开课-第四讲:快速排序 及 随机化 算法
    Win10的IIS与以前版本的一个区别
    干就行了!!!写程序就像珊瑚,分支太多,哪有那么多复用!
    NPoco的使用方法
    为什么前端要写标准代码?
    对于委托、事件、观察者模式最一目了然的代码段
    delphi处理消息的几种方式
    哎呀妈呀,吓死我了,幸好服务器没崩溃。
    Delphi的Hint介绍以及用其重写气泡提示以达到好看的效果
  • 原文地址:https://www.cnblogs.com/heben/p/9557798.html
Copyright © 2011-2022 走看看