• 搜索入门练习题5 八皇后问题 题解


    题目来源:《信息学奥赛一本通》例5.4

    题目描述

    要在国际象棋棋盘((8 imes 8) 的棋盘)中放 (8) 个皇后,使任意两个皇后都不能互相吃。(提示:皇后能吃同一行、同一列、同一对角线的任意棋子。)

    输出格式

    输出一个整数,用于表示八皇后问题的放置方案。

    题目分析

    首先我们用 ((x,y)) 来表示棋盘上第 (x) 行第 (y) 列的格子的坐标。
    那么,两个皇后 ((x_1,y_1))((x_2,y_2)) 会互相攻击当且仅当满足如下条件之一:

    • 在同一行:(x_1 = x_2)
    • 在同一列:(y_1 = y_2)
    • 在同一对角线:(x_1-x_2=y_1-y_2)(x_1-x_2=y_2-y_1) ,化简一下就是坐标差的绝对值相等,即: (vert x_1-x_2 vert = vert y_1-y_2 vert)

    我们可以用深度优先搜索来解决这道题。
    我们可以发现的是,要想在 (8 imes 8) 的棋盘上放置 (8) 个皇后,每一行都必须且只能放置一个皇后,所以我开一个数组 ans[]ans[id] 用于表示在第 id 行放置的皇后的列号。
    然后我开一个函数 f(id) ,用于表示:当前正准备在第 id 行放置一个皇后。然后我从 (1)(8) 去遍历列号 (i) ,如果 ((id,i)) 能放,则我尝试性地在 ((id,i)) 位置放上皇后,然后递归调用 f(id+1) , 直到 id>8 (说明找到了一种放置方案)为止。
    那么,我怎么去判断 ((id,i)) 这个位置能否放置一个皇后呢?我们搜索的顺序是从第 (1) 行一直到第 (8) 行的,所以当我要放置第 (id) 行的皇后的时候,肯定已经在第 (1)(id-1) 行放置好了前 (id-1) 个皇后。所以我只需要从 (1)(id-1) 去遍历行号 (j) ,比较一下第 (j) 行放置的皇后 ((j,ans[j])) 和我现在想要放的皇后 ((id,i)) 是否会相会攻击即可。
    如果这 (id-1) 个皇后都和 ((id,i)) 位置没有冲突,则说明 ((id,i)) 这个位置是可以放的,那我尝试性地在 ((id,i)) 位置放上皇后,并递归地进行下一步搜索 f(id+1)
    实现代码如下:

    #include <bits/stdc++.h>
    using namespace std;
    int ans[9], cnt; // ans[i]用于记录第i行皇后列号,cnt用于记录方案数
    // attack函数用于判断(x1,y1)和(x2,y2)两个点是否会互相攻击
    // 返回true:会互相攻击到;返回false:不会互相攻击到
    bool attack(int x1, int y1, int x2, int y2) {
        return x1==x2||y1==y2||abs(x1-x2)==abs(y1-y2);
    }
    // f函数用于在第id行尝试性地放一个i,然后递归地去id+1行放
    void f(int id) {
        if (id > 8) {   // 说明前8行已经放好了
            cnt ++;     // 找到一个方案,cnt++
            return;     // 程序可直接返回
        }
        for (int i = 1; i <= 8; i ++) { // 尝试在第id行第i列放皇后
            bool flag = true;   // flag用于标识是否能放
            for (int j = 1; j < id; j ++) {
                if (attack(id, i, j, ans[j])) { // (id,i)和(j,ans[j])冲突
                    flag = false;              // 将flag设为false标识不能放
                    break;
                }
            }
            if (flag) { // 如果循环结束flag仍为true说明i能放
                ans[id] = i;    // 能放就先放上
                f(id+1);        // 然后递归进行下一行的放置
            }
        }
    }
    int main() {
        f(1);   // 从第1行开始放
        cout << cnt << endl;    // 输出方案数
        return 0;
    }
    
  • 相关阅读:
    Prestashop-1.6.1.6-zh_CN (Openlogic CentOS 7.2)
    青石B2C商城
    装ubuntu的坑
    欧式空间和欧式距离、曼哈顿距离
    卷积神经网络入门
    pointnet++论文的翻译
    度量空间
    ppt演讲者视图不可用的解决办法
    pointnet
    Your CPU supports instructions that this TensorFlow binary was not compiled to use: AVX2 AVX512F FMA
  • 原文地址:https://www.cnblogs.com/zifeiynoip/p/11450705.html
Copyright © 2020-2023  润新知