AcWing
  • 首页
  • 课程
  • 题库
  • 更多
    • 竞赛
    • 题解
    • 分享
    • 问答
    • 应用
    • 校园
  • 关闭
    历史记录
    清除记录
    猜你想搜
    AcWing热点
  • App
  • 登录/注册

AcWing 843. n-皇后问题    原题链接    中等

作者: 作者的头像   双非懒蛋 ,  2025-02-04 23:39:09 ,  所有人可见 ,  阅读 7


0


目录

  • 1. 分析(朴素思路)
  • 2. 代码(朴素代码)
  • 3. 上述代码的问题
  • 4. 改进的代码

1. 分析(朴素思路)

枚举每个位置,枚举完一次,下一次(dfs)从下一行开始重新枚举。

注意三点:

  • 如何判断在同一斜线(y = x + b & y = -x + b)
  • 每次排除一行或一列,否则会有重复输出。每次最多排除一行或一列,否则如果同时排除一行和一列则无法输出正确答案。
  • 利用标记 continue。

2. 代码(朴素代码)

#include<iostream>

#define _rep_le(i, a, b) for(int i = (a); i <= (b); ++ i)
#define _rep_lt(i, a, b) for(int i = (a); i < (b); ++ i)
#define _rrep_ge(i, a, b) for(int i = (b); i >= (a); -- i)
#define _rrep_gt(i, a, b) for(int i = (b); i > (a); -- i)

using namespace std;

const int N = 10;

int n;
bool visitedCol[N], visitedRow[N], visitedSlide[2*N], visitedSlideR[2*N];
bool board[N][N];

void dfs(int row, int level) {
    if(level >= n) {
        _rep_lt(i, 0, n) {
            if(board[i][0] == false) cout << ".";
            else cout << "Q";
            _rep_lt(j, 1, n) {
                if(board[i][j] == false) cout << ".";
                else cout << "Q";
            }
            cout << endl;
        }
        cout << endl;
        return;
    }

    _rep_lt(i, row, n) {
        // for row
        if(visitedRow[i] == true) continue;
        _rep_lt(j, 0, n) {
            // for col
            if(visitedCol[j] == true) continue;
            if(visitedSlide[i-j+n] == true) continue;
            if(visitedSlideR[i+j] == true) continue;

            // Set Env
            /**
             * From y = x + b & y = -x + b, the relationship between
             * horizontal and vertical coordinates on the same oblique
             * lines can be obtained.
             * i.e. b = y - x & b = y + x
             */ 
            visitedRow[i] = true;
            visitedCol[j] = true;
            visitedSlide[i-j+n] = true;
            visitedSlideR[i+j] = true;
            board[i][j] = true;

            /**
             * If donot start from next line, there will be duplicate content.
             * Each recursion will exclude at most one row or one column,
             * and cannot reduce one row & one column at the same time.
             */ 
            dfs(i + 1, level + 1);

            // Recover Env
            visitedRow[i] = false;
            visitedCol[j] = false;
            visitedSlide[i-j+n] = false;
            visitedSlideR[i+j] = false;
            board[i][j] = false;
        }
    }

}


int main() {
    ios::sync_with_stdio(false);
    cin.tie(0);

    cin >> n;

    dfs(0, 0);

    return 0;
}

3. 上述代码的问题

“每次排除了一行下一次枚举下一行”这样的操作意味着同一行不可能重复选到。因此对于行的标记是没有意义的。

此外,在一次 dfs 中枚举完一行后,枚举下一行的时候,后面的行不可能枚举到前面的行,因此当前行不选一个位置,直接枚举下一行也是没有意义的。

因此我们的操作其实是:每次在对应的一行中枚举不同的位置,选择好后对下一行进行相同操作(dfs)直到每一行都选择完毕,然后输出一个答案。

4. 改进的代码

#include<iostream>

#define _rep_le(i, a, b) for(int i = (a); i <= (b); ++ i)
#define _rep_lt(i, a, b) for(int i = (a); i < (b); ++ i)
#define _rrep_ge(i, a, b) for(int i = (b); i >= (a); -- i)
#define _rrep_gt(i, a, b) for(int i = (b); i > (a); -- i)

using namespace std;

const int N = 10;

int n;
bool visitedCol[N], visitedSlide[2*N], visitedSlideR[2*N];
bool board[N][N];

void dfs(int row) {
    if(row >= n) {
        _rep_lt(i, 0, n) {
            if(board[i][0] == false) cout << ".";
            else cout << "Q";
            _rep_lt(j, 1, n) {
                if(board[i][j] == false) cout << ".";
                else cout << "Q";
            }
            cout << endl;
        }
        cout << endl;
        return;
    }

    _rep_lt(j, 0, n) {
        // for col
        if(visitedCol[j] == true) continue;
        if(visitedSlide[row-j+n] == true) continue;
        if(visitedSlideR[row+j] == true) continue;

        // Set Env
        /**
         * From y = x + b & y = -x + b, the relationship between
         * horizontal and vertical coordinates on the same oblique
         * lines can be obtained.
         * i.e. b = y - x & b = y + x
         */ 
        visitedCol[j] = true;
        visitedSlide[row-j+n] = true;
        visitedSlideR[row+j] = true;
        board[row][j] = true;

        /**
         * If donot start from next line, there will be duplicate content.
         * Each recursion will exclude at most one row or one column,
         * and cannot reduce one row & one column at the same time.
         */ 
        dfs(row + 1);

        // Recover Env
        visitedCol[j] = false;
        visitedSlide[row-j+n] = false;
        visitedSlideR[row+j] = false;
        board[row][j] = false;
    }
}


int main() {
    ios::sync_with_stdio(false);
    cin.tie(0);

    cin >> n;

    dfs(0);

    return 0;
}

0 评论

App 内打开
你确定删除吗?
1024
x

© 2018-2025 AcWing 版权所有  |  京ICP备2021015969号-2
用户协议  |  隐私政策  |  常见问题  |  联系我们
AcWing
请输入登录信息
更多登录方式: 微信图标 qq图标 qq图标
请输入绑定的邮箱地址
请输入注册信息