Loading

【算法学习】八皇后问题 递归算法

递归算法

 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() != '\n')
            {
                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;
}

 

posted @ 2018-08-30 00:27  注销111  阅读(549)  评论(0编辑  收藏  举报