洛谷1219N皇后

本文通过一个具体的6x6棋盘N皇后问题,介绍了如何利用回溯递归算法找到所有解决方案。博客详细解释了算法思路,强调了回溯递归的关键在于递归的退出条件和递归前后语句的处理。程序实现中,通过标记法避免在同一行、列和对角线上放置皇后,输出了前3个解,并给出了总解的数量。
摘要由CSDN通过智能技术生成

题目描述

一个如下的 6×66 \times 66×6 的跳棋棋盘,有六个棋子被放置在棋盘上,使得每行、每列有且只有一个,每条对角线(包括两条主对角线的所有平行线)上至多有一个棋子。

上面的布局可以用序列 2 4 6 1 3 52\ 4\ 6\ 1\ 3\ 52 4 6 1 3 5 来描述,第 iii 个数字表示在第 iii 行的相应位置有一个棋子,如下:

行号 1 2 3 4 5 61\ 2\ 3\ 4\ 5\ 61 2 3 4 5 6

列号 2 4 6 1 3 52\ 4\ 6\ 1\ 3\ 52 4 6 1 3 5

这只是棋子放置的一个解。请编一个程序找出所有棋子放置的解。
并把它们以上面的序列方法输出,解按字典顺序排列。
请输出前 333 个解。最后一行是解的总个数。
输入格式

一行一个正整数 nnn,表示棋盘是 n×nn \times nn×n 大小的。
输出格式

前三行为前三个解,每个解的两个数字之间用一个空格隔开。第四行只有一个数字,表示解的总数。
输入输出样例
输入 #1

6

输出 #1

2 4 6 1 3 5
3 6 2 5 1 4
4 1 5 2 6 3
4

说明/提示

【数据范围】
对于 100%100%100% 的数据,6≤n≤136 \le n \le 136≤n≤13。

笔者刚刚接触到dfs算法和回溯递归,关于dfs的思想仅有一点理解,处于大一的本人感觉与其说这道题是用dfs算法解答,倒不如说是回溯递归完美地实现了dfs算法.
对于n皇后问题,按行选择一个位置放置,对于任何一个被放置的点,假设其坐标为(x,y),其中x为行y为列,自左上到右下与其处于同一斜线的点其坐标之差为定值且等于x-y,自左下到右上与其处于同一斜线的点其坐标之和为定值且等于x+y。基于这一点分别建立三个数组(同列的y坐标相同)即可对放置皇后的坐标的两条斜对角线和同列直线进行标记(因为是逐行放置一个皇后不存在同行的情况),为了防止出现负数(数组的下标只能为正或0),用x-y+n(n为皇后数)来代替x-y即可。

#include <bits/stdc++.h>
#include <iostream>
using namespace std;

int n, a[3][100] = {0}, sum = 0, lay[100];//n为皇后数,sum存储解的个数,lay为放置皇后的点(输出)
//用行数为3的二维数组即可存储一个点的所处的三条直线的**坐标特征**,当然用3个一维数组也可
void dfs (int l)
 {
    if (l > n)
     {
        sum ++;
        if (sum > 3) return;
        for (int i = 1; i <= n; i++)
            cout << lay[i] << " ";
        cout << endl;
        return;
    }
    for (int i = 1; i <= n; i++) {
        if ((!a[0][i]) && (!a[1][l + i]) && (!a[2][l - i + n])) 
		{
            a[0][i] = 1;
			a[1][l + i] = 1; 
			a[2][l - i + n] = 1;
            lay[l] = i;
            dfs (l + 1);
            a[0][i] = 0; 
			a[1][l + i] = 0; 
			a[2][l - i + n] = 0;
        }
    }
} 

int main()
 {
    cin >> n;
    dfs (1);
    cout << sum << endl;
	return 0;
 }

关于回溯递归的关键,在于递归的退出条件和递归前递归后的语句.

洛谷皇后问题是一个经典的回溯算法问题。根据引用中的描述,要求将8个皇后放置在8*8棋盘上,使得它们彼此不受攻击,即任何两个皇后都不在同一行、同一列或同一斜线上。 引用[2]给出了一个c++代码的实现。这段代码使用了回溯法来解决八皇后问题。通过递归地尝试每一行中的每一列,找到合适的位置来放置皇后。 具体的过程如下: 1. 定义一个一维数组x,用来存储每行皇后的位置。 2. 从第一行开始递归,尝试每一列的位置。 3. 对于每个位置,检查是否与之前的皇后位置冲突,即是否在同一列或同一对角线上。如果冲突,就继续尝试下一列;如果不冲突,就将该位置存入数组x,并继续递归下一行。 4. 当递归到最后一行时,打印出当前的皇后位置,并将可行解的数量加一。 5. 回溯到上一行,尝试下一个列的位置。 6. 当所有的解都找到后,输出解的数量。 根据引用给出的代码,共有92种不同的放置方式,即解的数量为92。<span class="em">1</span><span class="em">2</span> #### 引用[.reference_title] - *1* [8皇后_八皇后问题c++实现_](https://download.csdn.net/download/weixin_42665725/26278676)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] - *2* [八皇后问题C++递归回溯法(注解)](https://blog.csdn.net/qq_43656233/article/details/105571396)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值