洛谷-----P1219 八皇后

1、题目描述

        题目链接:https://www.luogu.org/problem/P1219

2、分析

        n后问题有四个限制条件,首先是行,这一行不能再有其他皇后,由于我们是使用行来做递归,在放置第i个皇后时,必然行的条件是满足的,那么就需要考虑列和对角线的条件,首先在递归程序里需要遍历所有的列,要在这些列里找到没有被标记过的点,如果找到,那么这个点就是当前第i个皇后所在的列,可以将其记录,之后,我们需要对这个皇后所在的列和对角线进行标记,对列的标记很简单,使用一个数组A[i]=j,表示第i个皇后占有了在第j列。这个j就是递归函数里的遍历的条件。至于对角线的标记,假设两个皇后的位置分别是(x1,y1)(x2,y2),那么怎么证明他们在一条斜线上,其实很简单,分两种情况,从左上角到右下角,这条线上的点坐标的(x1,y1)和(x2,y2), 且 x1-y1 = x2- y2 或 x1+y1 = x2+y2,则说明这2个皇后处于同一斜线上。这里可以用i+j表示表示一个占用过的斜线,用i-j表示一个占用的斜线,i-j有可能小于0,可以为其加上N来让其不至于小于0,如下程序,输入N小于等于13,那么i+j小于等于26,所以可以用一个数组来表示。所以一共需要三个数组来表示占用过的列,和两个对角线。需要注意的是递归完了之后需要回溯。

3、代码

#include<stdio.h>
#include<iostream>
using namespace std;
int res[14];//存储每一行放置的位置
int check_res[3][28];//判断列和对角线
int N;
int answer=0;
void dfs(int step){
    if (step > N){
        answer++;
        if (answer > 3){
            return;
        }
        else{
            for (int i = 1; i <= N; ++i){
                cout << res[i] << " ";
            }
            cout << endl;
            return;
        }
    }
    for (int j = 1; j <= N; j++){
        if (!check_res[0][j] && !check_res[1][step + j] && !check_res[2][step - j + N]){
            res[step] = j;
            check_res[0][j] = 1;
            check_res[1][step + j] = 1;
            check_res[2][step - j + N] = 1;
            dfs(step + 1);
            check_res[0][j] = 0;
            check_res[1][step + j] = 0;
            check_res[2][step - j + N] = 0;
        }
    }
}

int main(){
    cin >> N;
    dfs(1);
    cout << answer;
    return 0;
}

4、相关知识点

        递归和回溯。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值