N皇后问题的二进制优化详细思路

N皇后问题和优化 N皇后问题及其优化,主要是对角线和副对角线的判断上面的优化。输入要求的皇后数目n,输出有多少种排列的数目。 九度OJ1254已经AC 立即下载

题目啊常规解法(DFS)在此就不赘述了。。。

直接进入正题

众所周知,N皇后是NP完全类问题,n稍微大了点求解过程就会变得很长。

算法方面很难再有质的效率突破,但这不妨在其他细节上下下功夫。

揆诸常规解法,采用了数组来做mark,以行为每一层进行回溯算法,每个操作周期中无非就做了下面这些事情:

更新元素

判定元素

做出反应

更新元素这上面基本上想不到能有啥提升空间了(一次更新多个??似乎更加复杂了不谈不谈)。。。

做出反应嘛也同样没啥可以进步的地方(做出预判类反应??也复杂了,不谈不谈)。。。

很显然,有提升空间的就是判定元素环节了。

首先,从存储上考虑:

我们采用了三个数组来分别mark两个斜线和一列的占用情况(这里用"占用情况"表示此处是否能落子,如果被‘占用了’,则不能放棋子)

可不可以并成一个数组呢?那么这一个数组就要能够表示三个信息:当前位置一列两斜线的占用情况。有时即使能表示了,但是当移动到下一个位置的时候又得获得新的信息。。似乎不可行。

(于是我们又开始无聊地在纸上模拟算法过程了。。。。)

诶,然后就会发现,当进行DFS的时候,比如进行到第k层,放下了一个棋子,然后我们就要到下面一层去继续判定,此刻我们用到的信息是第k+1层的占用情况,而k+1的占用情况受到第k层情况的直接影响,如下图:

 我们会发现第三层涂色的三个位置就不能放棋子了, 

而除了第k层的影响,前k-1层也对第k+1层有着制约:

再回来看经典算法,每一次标记直接就否定了一条线上的位置,我们跳出这个思维,可不可以“步步为营”,进入到下一行的同时更新出下一行的占用信息?如果这样的话,一个数组足矣。  

再思考,都已经一个数组了(相当于一串数字),而且每个格子就两个状态:有棋子,没棋子。

显然,二进制是不二选择!而且二进制运算的效率比较高!

大概的思路出来了,还有最后一个难点,就是前k-1层的占用信息如何安全过度到第k+1行。。

动手尝试了就不难发现这个规律:一个棋子会产生三种影响效果,斜向影响的,到下一层“占用”会斜向相应的方向偏移一格;垂直影响的,到下一层“占用”依旧在相应位置。

如图:

这时候就出现了三种类型的信息更新,一串二进制就难以实现了。。。那就三串呗,比起数组仍然不亏了。

大的逻辑疙瘩在脑子里基本上解开了,下面开始改代码:

首先,咱不用数组,改成int就够了。其次,考虑到每次信息更新的特点,我们可以用函数的形参来传递,省的搞个全局变量让人不爽。

函数头这亚子:

void Dfs(int i,int left,int col,int right)//分别是 层数  反斜杠mark  一列mark  斜杠mark 

然后仍然是一般DFS解法的框架,只需要把其中用bool数组mark判断的地方用二进制方法进行替换即可。 

放代码:

void Dfs(int i,int left,int col,int right)//分别是 层数  反斜杠mark  一列mark  斜杠mark
{
    if (i > N)              //判断是否已经枚举完了N行
    {
        showOneSolution();  //枚举完了就输出(此刻我们处于N+1行)
        return;             //返回到第N行
    }
    for (int j = N-1; j >=0; --j) //为啥J倒过来数呢?方便下面if中的偏移判断
    {
        if (!(((left|col|right)>>j)&1))//(自己解读,有助于提升能力 (好吧我懒))
        {
            ans[i] = N-j;
            Dfs(i + 1,(left|(1<<j))<<1,(col|(1<<j)),(right|(1<<j))>>1);  //更新“占用信息”的工作就放在参数传递这里了
                                              //这样子的好处就是,回溯的时候不用做什么恢复处理,
                                              //因为这一层的东西基本没变动
        }
    }
}

这么多括号嵌套的。。哎呀我知道这可读性差,不提倡不提倡!

但是咱们现在是学习又不是工作,尽量读一些奇怪的代码有助于提高读代码能力(可着劲找借口··)

好了下面放上完整代码:

#include<iostream>

using namespace std;

int total = 0;
int N = 0;
int ans[64] = { 0 }; //结果还是要用数组存滴
void showOneSolution()//用来显示一个解
{
    total++;
    for (int i = 1; i<=N; ++i)
    {
        cout << ans[i] << " ";
    }
        cout << endl;
}
void Dfs(int i,int left,int col,int right)//分别是 层数  反斜杠mark  一列mark  斜杠mark
{
    if (i > N)              //判断是否已经枚举完了N行
    {
        showOneSolution();  //枚举完了就输出(此刻我们处于N+1行)
        return;             //返回到第N行
    }
    for (int j = N-1; j >=0; --j) //为啥J倒过来数呢?方便下面if中的偏移判断
    {
        if (!(((left|col|right)>>j)&1))//(自己解读,有助于提升能力 )
        {
            ans[i] = N-j;
            Dfs(i + 1,(left|(1<<j))<<1,(col|(1<<j)),(right|(1<<j))>>1);  //更新“占用信息”的工作就放在参数传递这里了
                                              //这样子的好处就是,回溯的时候不用做什么恢复处理,
                                              //因为这一层的东西基本没变动
        }
    }
}

int main()
{
    cin >> N;
    Dfs(1,0,0,0);
    cout << total;
    system("pause");
    return 0;
}

总结:

  巧妙运用位运算可以达到锦上添花的效果(装逼),不过大多数人看到位运算&|^<<>>啥的就打哈欠。

  但是恰巧就有那么一些问题,能够完美契合二进制和位运算的特殊性质(不是指这个==),当你遇到的时候,你就会惊异于0101010···的奇妙。  


后记:

  当年还是太年轻,其实既然都用了位运算,为何不用用这个绝妙的性质呢?

    x & (−x) 可以获得 x 的二进制表示中的最低位的 1 的位置;

    x & (x−1) 可以将 x 的二进制表示中的最低位的 1 置成 0。

南大计算机2024保研笔试:编译原理等5门专业课考点分布与408复习避坑指南 本文详细解析了南京大学计算机2024保研笔试的考点分布与复习策略,重点突出编译原理(占比28%-32%)和离散数学的特色考核。提供跨课程复习方法、真题题型分析及高效备考建议,帮助考生突破传统408框架,应对南大独特的命题风格。 阅读详情

相关推荐

Python+Selenium实现抖音博主批量监控:300+账号实时更新通知(附完整代码)

本文详细介绍了如何使用Python和Selenium构建一个高可用的抖音博主批量监控系统。通过架构设计、Cookie管理、高效轮询与差异检测等核心模块,实现300+账号的实时更新追踪与通知。文章提供了完整的代码实现,并重点探讨了性能优化、异常处理及服务器部署等实战经验,帮助开发者打造稳定、可控的自动化监控解决方案。

weixin_29274969的博客 193

NP-Hard问题

N皇后问题是一个NP-Hard问题,其算法复杂度是指数复杂度的。 ①图着色问题 ②哈密顿回路问题:天文学家哈密顿(William Rowan Hamilton) 提出,在一个有多个城市的地图网络中, 寻找一条从给定的起点到给定的终点沿途恰好经过所有其他城市一次的路径。这个问题和著名的过桥问题的不同之处在于,某些城市之间的旅行不一定是双向的。比如A→B,但B→A是不允许的。 ③TSP问题 ...

caoyongsheng的博客 1585

中国境内及周边2839个站点的日降水量逐日降水数据集(1961-2022,0.1°/0.25°/0.5°)1、数据年份:1961-2022,日数据2、数据范围:中国境内及周边2839个站点的日降

CHM_PRE数据集基于中国境内及周边1961至今共2839个站点的日降水观测,在传统的“降水背景场+ 降水比值场”的数据集构建思路上,尝试应用月值降水约束和地形特征校正,并依据中国范围内约4万个高密度站点2015–2019年的日降水量插值后数据进行精度评价。

yushibing717的博客 2787

N皇后问题 各种优化

0.问题引入 N皇后问题是一个经典的问题,在一个N*N的棋盘上放置N个皇后,每行一个并使其不能互相攻击(同一行、同一列、同一斜线上的皇后都会自动攻击),问有多少种摆法。 题目链接:https://www.luogu.org/problemnew/show/P1219 1、普通回溯 回溯算法也叫试探法,它是一种系统地搜索问题的解的方法。回溯算法的基本思想是:从一条路往前走,能进则进,不能进...

weixin_30273763的博客 220

【算力网络】算力知识

尽管算力这个词在近年来很“火”,但其背后的含义,却很少有人真正了解

qq_42809645的博客 1万+

Python+whisper/vosk实现语音识别

Whisper 是一个由 OpenAI 开发的人工智能语音识别模型,它能够将语音转换为文本。Whisper 模型特别之处在于它的设计目标是能够理解和转录多种语言的语音,包括但不限于英语。Whisper 模型在训练时使用了大量不同语言的语音数据,这使得它具有很好的跨语言能力。Vosk 是一个开源的语音识别库,它可以在离线环境下工作,不依赖于任何外部服务。Vosk 基于Kaldi语音识别框架,支持多种语言,包括中文。Vosk提供了多种预训练模型,可以根据需求选择适合的模型进行语音识别。

weixin_44458771的博客 5939

使用位运算优化 N 皇后问题

本文主要讲述了 N 皇后算法和位运算优化解法。

Practitioner 530

华为OD机试2025C卷 - CPU调度策略 (C++ & Python & JAVA & JS & GO)

华为OD机试 2025C卷 CPU调度策略,提供Java、C++、Python、Go、JavaScript源码实现,并提供完整思路讲解

qq_45776114的博客 1296

随机化算法的初步实践-N 后等问题

c++做随机化算法的初步实践-N 后等问题

qq_61166620的博客 1060

国家自然基金研究方向选定后,关键词只能下拉吗?——不是的,国家自然科学基金(NSFC)的关键词并不是只能下拉选择,而是:[特殊字符] “可选 + 可填”的混合模式(但以规范词为主)

你可以手动输入关键词用于表达新兴方向或细分领域✔ 适用情况:新概念(如“电场调控纳米流体”)交叉领域(如“电流体力学传热耦合”)电场调控电流体力学可以自己填,但必须以系统标准关键词为主,自定义为辅如果你愿意,我可以帮你做一件更关键的事:👉根据你题目,反向设计“最容易中标”的关键词组合 + 学科代码搭配这个比写内容本身还更影响送审质量。你可以手动输入关键词用于表达新兴方向或细分领域✔ 适用情况:新概念(如“电场调控纳米流体”)交叉领域(如“电流体力学传热耦合”)电场调控电流体力学。

qq_15963745的博客 81

5.30华为OD机试真题 新系统 - 链表数字游戏 (Java/Py/C/C++/Js/Go)

5.30华为OD机试真题 新系统 - 链表数字游戏 (Java/Py/C/C++/Js/Go)

算法大师! 1118

N皇后问题(各种优化)

0.问题引入 N皇后问题是一个经典的问题,在一个N*N的棋盘上放置N个皇后,每行一个并使其不能互相攻击(同一行、同一列、同一斜线上的皇后都会自动攻击),问有多少种摆法。 题目链接:https://www.luogu.org/problemnew/show/P1219 1、普通回溯 深搜+回溯,它是一种系统地(能找到全部的解)搜索问题的解的方法。 基本思想是:从一条路往前走,能进则进,不能进则退回来,换一条路再试。 算法思想: 1. 在第k(1≤k≤N)行选择一个位置,判断这个位置是否可以摆,可以摆就进入第

https://github.com/ZichengCao 2399

论文阅读:Universal and Transferable Adversarial Attacks on Aligned Language Models. LLM Attacks

因为“即开即用”的大型语言模型能够生成大量令人反感的内容,近期的工作集中在对这些模型进行对齐,以防止不受欢迎的生成。尽管在规避这些措施方面取得了一些成功——即所谓的针对大型语言模型(LLMs)的“越狱”——这些攻击需要大量的人类智慧,并且在实践中很脆弱。自动对抗性提示生成的尝试也取得了有限的成功。在本文中,我们提出了一种简单有效的攻击方法,可以导致对齐的语言模型生成令人反感的行为。

CSPhD-winston的博客 1416

【经典算法】N皇后问题

经典N皇后问题的算法。做一道经典题目,来一场思维旅行。

ai15013602354的博客 1万+

jre9下载 jdk9

(Java SE Runtime Environment 9.0) 9.0u175 官方最新版 【x86|x64】

WINCC7.3破解文件

WINCC7.3硬件够破解文件,有需要的下载!WINCC7.3硬件够破解文件,有需要的下载!

位运算解决N皇后 详细图解

解决N皇后常用的方式是使用三个set来进行判重,分别存储列方向,撇方向和捺方向。每到新的一行,在准备放皇后的时候,就分别在三个集合中进行查找,若列的集合种没有出现当前列,则说明当前列是可以进行放置的,然后再分别看看,撇方向和捺方向的集合,若仍然没有出现与之对应的记录,则说明该位置可以放置皇后。然后继续进行DFS。而解决N皇后问题的最高级的做法便是使用位运算。 题目链接: LeetCode-52...

ZhaoSimonone的博客 3330

Statistics and Machine Learning Toolbox

Statistics and Machine Learning Toolbox(带书签),MATLAB统计学习工具

皇后问题

八皇后问题是一个以国际象棋为背景的问题:如何能够在 8×8 的国际象棋棋盘上放置八个皇后,使得任何一个皇后都无法直接吃掉其他的皇后?为了达到此目的,任两个皇后都不能处于同一条横行、纵行或斜线上。八皇后问题可以推广为更一般的n皇后摆放问题:这时棋盘的大小变为n1×n1,而皇后个数也变成n2。而且仅当 n2 ≥ 1 或 n1 ≥ 4 时问题有解。 皇后问题是非常著名的问题,作为一个棋盘类问题,毫无疑...

少说,多做。 2万+

OV9734 DATASHEET,完整规格书

OV9734完整规格书,包括电气参数,尺寸规格,寄存器配置表等

程序员面试题------N皇后问题算法实现

N皇后问题是一个著名的计算机科学问题,它要求在N×N的棋盘上放置N个皇后,使得它们之间不能相互攻击,即任意两个皇后都不能处于同一行、同一列或同一斜线上。这个问题可以看作是一个回溯算法问题,通过逐步尝试不同的放置位置,并在发现不满足条件时回溯到上一步,来找到所有可能的解。

xx 1421

回溯法之----N皇后问题,全排列问题,求子集问题

N皇后问题 N皇后问题是八皇后问题的升级版主要思路也是通过回溯法来实现的 这列通过对角线判断进行了适当的优化 首先先贴上代码 #include <iostream> using namespace std; int cnt; int a[12]; int col[12]; int dig1[24]; int dig2[24]; void placeQueen(int k,int &am...

weixin_42413719的博客 434

n皇后问题的回溯and位运算解法

题目内容: n皇后游戏要求在一个n×n的棋盘上放置n个皇后,使n个皇后互相不攻击(攻击的含义是有两个皇后在同一行或同一列或同一对角线上)。求有多少种放置方法。 ① 回溯法 未经优化的暴力解法。虽然很暴力,而且一般就会TLE,但是简单易懂,会给一些优化代码做铺垫。 int c[N]; void dfs(int cur,int n){ if(cur==n) ans++; else for(int i=0;i<n;i++){ int flag=1;c[cur]=i; for(int

weixin_45883286的博客 349

图论 - 深度优先搜索 - n皇后问题

n皇后问题 描述 n皇后问题:一个n×n的棋盘,在棋盘上摆n个皇后,满足任意两个皇后不能在同一行、同一列或同一斜线上的方案有多少种? 输入 第一行包含一个整数n。 输出 输出一个整数,表示方案数。 样例输入 4 样例输出 2 限制 一共10个测试点, 第i个测试点的n=i+4。 时间:2 sec 空间:512 ...

weixin_30458043的博客 252

N皇后问题

/ **N皇后问题**是一个经典的回溯算法问题,要求在 `N × N` 的棋盘上放置 `N` 个皇后,使得它们彼此之间**不能互相攻击**。// 根据国际象棋规则,皇后可以攻击同一行、同一列或同一对角线上的任意棋子。2. **检查冲突**:每次放置前,检查当前列和两条对角线上是否已有皇后。1. **逐行放置皇后**:从第 `0` 行开始,尝试在每一列放置皇后。4. **终止条件**:所有行都成功放置皇后时,记录一个解。// #### **1. 什么是N皇后问题?#### **2. 解决思路(回溯法)**

tankeven的博客 436

暴力递归之N皇后问题(利用位运算优化)

题目描述 现在给你一个长为N,宽为N的棋盘,现在需要你往棋盘上放N个皇后,并且要求,任意两个皇后不能在同一行,同一列,同一个对角线。请求出一共有多少种放置方法。 思路分析 首先,此题用暴力递归,也就是举出所有的可能性可以解决。但是,暴力递归时间复杂度太高,一般将暴力递归改成动态规划比较好。但是,此题不能修改成动态规划,因为此题的中间状态是包含后效性的,也就是说,此题的中间任意一个递归状态,是和之前到达这个状态的路径有关的,因此,此题不能修改成动态规划,只能暴力递归求解。 暴力递归思路: 我们用一个数组arr

weixin_43923436的博客 331

八皇后问题的解决与优化

在 8×8 的国际象棋棋盘上放置 8 个皇后,使得任意两个皇后不能处于同一行、同一列或同一斜线上,求所有可能的放置方案。这个问题看似简单,实则蕴含着深刻的算法思想 —— 它是回溯法(Backtracking)的典型应用场景,同时也是算法面试中的高频考点。行约束:每一行仅能放置一个皇后(可通过行遍历天然满足);列约束:任意两个皇后不能在同一列;对角线约束:任意两个皇后不能在同一主对角线(斜率为 1)或副对角线(斜率为 - 1)。

lylylyl_的博客 715

搜索回溯n皇后问题C++模板

在计算机科学中,N皇后是经典的回溯算法例题,用于演示如何高效解决组合优化问题。随着N增大,解的数量呈指数级增长(如N=8时有92种解),直接暴力枚举不可行,需借助回溯剪枝。:N皇后问题源自国际象棋,规则为皇后可攻击同行、同列或同一斜线的棋子。问题最早由19世纪棋手马克斯·贝瑟尔提出,数学家高斯曾研究但未完全解决。通过回溯法,N皇后问题不仅展示了暴力枚举与智能搜索的效率差异,还为复杂约束问题提供了通用解决框架。:逐行放置皇后,若当前行无合法位置,则回溯到上一行调整。

m0_66655785的博客 531

洛谷P1219N皇后问题

其实这个八皇后问题本身并不难理解,这里主要是想分享一下位运算来进行状态压缩的神奇之处,也帮自己加深一下印象,本身位运算又比数组取值要快一些,在dfs过程中需要大量计算取值,这样我们巧妙地运用位运算就可以既减少空间小耗又减少时间消耗。如果觉得有点帮助的话帮忙点个小赞,让更多人可以看到吧~

m0_74246669的博客 2186

算法040(必备)——N皇后问题

研究的是如何将n个皇后放置在n × n的棋盘上,并且使皇后彼此之间不能相互攻击。给你一个整数n,返回不同的解决方案的数量。

x_2023_713的博客 542
上一篇: 逆向解读割木板问题贪心算法合理性
下一篇: (新手向)N皇后问题详解(DFS算法)
咖啡咖_CoffCa
博客等级 码龄6年 116粉丝 58原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

咖啡咖_CoffCa

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值