zoukankan      html  css  js  c++  java
  • 八皇后问题

    问题描述

    问题描述:在棋盘上放置 8 个皇后,使得它们互不攻击,此时每个皇后的攻击范围为同行同列同对角线,要求找出所有解。

    LeetCode上面的描述:

    20201217212430

    解决方法

    这里使用经典的回溯法。

    代码:

    下面的程序简洁地求解了八皇后问题。在主程序中读入 n,并为 tot 清零,然后调用 search(0),即可得到解的个数 tot。

    void search(int cur) { // cur 代表当前行
        if (cur == n)
            tot++; // 递归边界, 只要走到了这里, 所有皇后必然不冲突, 因为这是从第 8 行(也就是最后一行)递归进来的
        else {
            for (int i = 0; i < n; i++) { // 对列进行遍历
                int ok = 1; // 记录当前的摆放位置是否会和之前已经放好的皇后发生冲突
                C[cur] = i;
                for (int j = 0; j < cur; j++) { // 检查是否和前面的皇后冲突
                    if (C[cur] == C[j] || cur - C[cur] == j - C[j] || cur + C[cur] == j + C[j]) {
                        ok = 0;
                        break;
                    }
                }
                if (ok)
                    search(cur + 1);
            }
        }
    }
    

    这里的测试结果是 92,答案正确。

    这个程序还可以改进,如下

    int total = 0;
    int vis[3][N * 2] = {0}; // vis[0] 表示列被占据的情况, vis[1] 表示主对角线(从左上到右下)被占据的情况, vis[2] 表示副对角线被占据的情况
    void searchV2(int cur) {
        if (cur == n) {
            total++;
        } else {
            for (int i = 0; i < n; i++) {
                if (!vis[0][i] && !vis[1][cur + i] && !vis[2][cur - i + n]) { // 利用二维数组直接判断
                    C[cur] = i;
                    vis[0][i] = vis[1][cur + i] = vis[2][cur - i + n] = 1; // 修改全局变量
                    searchV2(cur + 1);
                    vis[0][i] = vis[1][cur + i] = vis[2][cur - i + n] = 0; // 切记! 一定要改回来
                }
            }
        }
    }
    

    关于 vis 数组的说明:它表示已经放置的皇后占据了那些列、主对角线和副对角线。上面的注释也详细说明了这一点。经测试,这个代码跑出来的结果是正确的。

    完整代码

    #include <iostream>
    #include <ctime>
    
    #define N 8
    
    int n = 8;
    int tot = 0; // total, 用于记录可能的种数
    int C[N] = {-1, -1, -1, -1, -1, -1, -1, -1};
    
    void search(int cur) { // cur 代表当前行
        if (cur == n)
            tot++; // 递归边界, 只要走到了这里, 所有皇后必然不冲突, 因为这是从第 8 行(也就是最后一行)递归进来的
        else {
            for (int i = 0; i < n; i++) { // 对列进行遍历
                int ok = 1; // 记录当前的摆放位置是否会和之前已经放好的皇后发生冲突
                C[cur] = i;
                for (int j = 0; j < cur; j++) { // 检查是否和前面的皇后冲突
                    if (C[cur] == C[j] || cur - C[cur] == j - C[j] || cur + C[cur] == j + C[j]) {
                        ok = 0;
                        break;
                    }
                }
                if (ok)
                    search(cur + 1);
            }
        }
    }
    
    
    int total = 0;
    int vis[3][N * 2] = {0}; // vis[0] 表示列被占据的情况, vis[1] 表示主对角线(从左上到右下)被占据的情况, vis[2] 表示副对角线被占据的情况
    void searchV2(int cur) {
        if (cur == n) {
            total++;
        } else {
            for (int i = 0; i < n; i++) {
                if (!vis[0][i] && !vis[1][cur + i] && !vis[2][cur - i + n]) { // 利用二维数组直接判断
                    C[cur] = i;
                    vis[0][i] = vis[1][cur + i] = vis[2][cur - i + n] = 1; // 修改全局变量
                    searchV2(cur + 1);
                    vis[0][i] = vis[1][cur + i] = vis[2][cur - i + n] = 0; // 切记! 一定要改回来
                }
            }
        }
    }
    
    int main() {
        clock_t start_time, end_time;
    
        start_time = clock();
        for (int i = 0; i < 10000; i++) {
            tot = 0;
            search(0);
        }
        end_time = clock();
        std::cout<<end_time - start_time<<std::endl;
        std::cout<<"一共有"<<tot<<"种解法"<<std::endl;
    
        start_time = clock();
        for (int i = 0; i < 10000; i++) {
            total = 0;
            searchV2(0);
        }
        end_time = clock();
        std::cout<<end_time - start_time<<std::endl;
        std::cout<<"一共有"<<total<<"种解法"<<std::endl;
        return 0;
    }
    

    测试结果:

    2897
    一共有92种解法
    1020
    一共有92种解法
    
  • 相关阅读:
    记一次坑爹的jconsole使用
    触发Full GC的时机
    java NIO之Selector
    java NIO之SelectedKey
    java泛型中的各种限制
    filebeat安装部署
    Kibana安装及简单使用
    elastucasearch基础理论以及安装
    Salt 与Salt API配置
    RabbitMQ 相关理论部分
  • 原文地址:https://www.cnblogs.com/fanlumaster/p/14152079.html
Copyright © 2011-2022 走看看