n皇后问题的最优解及优化

news2024/10/6 22:19:48

n皇后问题的最优解

时间复杂度    O(n^{n})

package algorithm;

public class NQueen {
    public static int num(int n){
        if(n < 1){
            return 0;
        }
        int[] record = new int[n];//n皇后的n*n的棋盘,record[i]表示第i行的皇后放在了第几列
        return process(0,record,n);
    }

    /**
     *返回n皇后的摆法
     * i表示从第几行开始,n表示皇后数
     */
    private static int process(int i, int[] record, int n) {
        //如果当前的位置在i行,那么即表示i-1及之前的行的皇后一定是满足条件的,在摆第i行的皇后要满足条件不与之前的皇后共行、共列或共线
        //如果行数来到n,说明已经来到最后,此时即为出现一种摆法
        if(i == n){
            return 1;
        }

        int res = 0;
        //遍历列
        for (int j = 0; j < n; j++) {
            if(isValid(record,i,j)){//判断是否能摆
                record[i] = j;//能摆久记录摆下的皇后的列
                res += process(i+1,record,n);//递归,摆下一行,在下一行依旧遍历所有列
            }
        }
        return res;
    }

    //判断是否共行、共列、共斜线
    //由于record数组的索引存储的就是行数,因此不需要检查是否共行
    private static boolean isValid(int[] record, int i, int j) {
        for (int k = 0; k < i; k++) {
            //检查是否共列、共斜线(纵坐标之差 == 横坐标之差)
            if(j == record[k] || Math.abs(record[k] - j) == Math.abs(i-k)){
                return false;
            }
        }
        return true;
    }
}

上述最优解在n的值较大的时候跑出来仍是很慢,但无法对此进行结构上的优化,即无法进行时间复杂度的优化,但是可以使用位运算进行常数时间上的优化

优化

条件:不超过32皇后问题,超过32皇后问题需要把int转化为long类型

举个栗子

八皇后问题,n = 8

1位置不能放皇后,0位置可以

第1行00001000
列限制00001000
左斜线限制00010000
右斜线限制00000100
三个限制求或00011100
1
第2行01000000
第2行+第1行限制11101010

左斜线限制 = 列数 -  行差(左移)

右斜线限制 = 列数 + 行差(右移)

利用位运算的特性,限制哪些列可以放皇后,而不是每一列都遍历,节省时间

int pos = limit & (~(colLim | leftDiaLim | rightDiaLim));

第一个数表示前面的数,limit即前面都是0,后面8位都是1

limit011111111
列限制000001000
左斜线限制000010000
右斜线限制000000100
三种限制或000011100
~取反111100011
&并limit011100011

为什么要有limit?

因为可以和limit求并截去左侧的所有的数,在最终求得的pos数中,1的位置可以放置皇后,0的位置不可以放置皇后

mostRightOne = pos & (~pos + 1);
pos011100011
~pos100011100
~pos+1100011101
pos&(~pos+1)000000001

package algorithm;

public class NQueenOptimize {
    public static int num(int n) {
        //不超过32皇后问题
        if (n < 1 || n > 32) {
            return 0;
        }
        //生成一个二进制位数,后n位都是1,前面都是0
        //limit数本身的值不重要,只是用它的位信息
        int limit = -1;//n == 32
        if (n != 32) {
            limit = (1 << n) - 1;
        }
        return process(limit, 0, 0, 0);
    }

    /**
     * 1的位置不可以放皇后,0可以
     * colLim: 列的限制
     * leftDiaLim: 左斜线的限制
     * rightDiaLim: 右斜线的限制
     */
    private static int process(int limit, int colLim, int leftDiaLim, int rightDiaLim) {
        //列上的限制 == limit,说明全都放满了,此时即为一种摆法
        if (colLim == limit) {
            return 1;
        }

        /**
         * pos表示所有候选皇后的位置,1的位置可以放皇后,0的位置不可以放皇后
         * (colLim | leftDiaLim | rightDiaLim) 三种限制或
         * ~ 表示取反,此时在棋盘上1表示可以放皇后,0表示不能放皇后
         * & 和limit求与(0和1与为0,1和1与为1)
         */
        int pos = limit & (~(colLim | leftDiaLim | rightDiaLim));

        int res = 0;
        int mostRightOne = 0;
        
        //在每个1的位置上尝试皇后的位置,在尝试之后将值修改为0
        while (pos != 0) {
            mostRightOne = pos & (~pos + 1);
            pos = pos - mostRightOne;
            //左右限制变化
            res += process(limit,
                    colLim | mostRightOne,
                    (leftDiaLim | mostRightOne) << 1,
                    (rightDiaLim | mostRightOne) >> 1);
        }
        return res;
    }

}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1282800.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

PLC通过485Modbus转Profinet网关与温控表通讯在发酵罐的应用

前提&#xff1a;在自动化控制系统中&#xff0c;PLC通常需要和各种设备进行数据通讯&#xff0c;其中就包括温控表。而这些设备之间的通讯常常需要通过485Modbus转Profinet网关&#xff08;XD-MDPN100&#xff09;来实现。 方案&#xff1a;在一些应用场合中&#xff0c;Profi…

一种结构新颖的双通带超导滤波器设计

闫鑫1,2&#xff0c;季来运1&#xff0c;张浩1,2&#xff0c;李颢毅1,2&#xff0c;王昭月1,2&#xff0c;曹凤莹1,2 &#xff08;1.天津海芯电子有限公司&#xff0c;天津300380&#xff1b;2.天津师范大学物理与材料科学学院&#xff0c;天津 300387.&#xff09; 摘要&…

CUDA简介——同步

1. 引言 前序博客&#xff1a; CUDA简介——基本概念CUDA简介——编程模式CUDA简介——For循环并行化CUDA简介——Grid和Block内Thread索引CUDA简介——CUDA内存模式 本文重点关注Thread同步和Barriers。 Threads并行执行&#xff0c;可能存在如下问题&#xff1a; 1&#…

Mybatis 操作续集(结合上文)

当我们增加一个数据之后,如果我们想要获取它的 Id 进行别的操作,我们该如何获取 Id 呢? 用那个Options package com.example.mybatisdemo.mapper;import com.example.mybatisdemo.model.UserInfo; import org.apache.ibatis.annotations.*;import java.util.List;Mapper pub…

读SAM代码

def add_decomposed_rel_pos(attn: torch.Tensor,q: torch.Tensor,rel_pos_h: torch.Tensor, 27,80的全零训练参数rel_pos_w: torch.Tensor,q_size: Tuple[int, int], (14,14)k_size: Tuple[int, int], ) -> torch.Tensor:计算相对位置嵌入"""Calculate deco…

中危漏洞!小程序优惠卷遍历

进入小程序&#xff0c;因为是一个小商城&#xff0c;所以照例先查看收货地址是否存在越权&#xff0c;以及能否未授权访问&#xff0c;但是发现不存在这些问题&#xff0c;所以去查看优惠卷 进入领券中心&#xff0c;点击领取优惠券时抓包 发现数据包&#xff0c;存在敏感参数…

HTTP 和 HTTPS的区别

一、HTTP 1.明文传输&#xff0c;不安全 2.默认端口号&#xff1a;80 3.TCP三次握手即可 二、HTTPS 1.加密传输&#xff0c;更安全(在HTTP层与TCP层之间加上了SSL/TTL安全协议) SSL和TTL是在不同时期的两种叫法&#xff0c;含义相同。 2.默认端口号&#xff1a;443 3.TCP三…

Java集合(已重写-废弃了)

# 精辟总结 其实各种八股文资料&#xff0c;他也就是围绕着核心知识展开提问的&#xff0c;你只要根据八股文把核心知识提炼出来&#xff0c;形成核心知识体系&#xff01; Java集合那是重点中的重点。最基本的概念要懂&#xff0c;核心的概念&#xff0c;那要滚瓜烂熟。 Ja…

python flask Jinja2模板学习

分类很好的一篇文章 Jinja2模板语法 Jinja2里常见的三种定界符&#xff1a; (1) 语句 {% ... %}(2) 表达式 {{ ... }}(3) 注释 {# ... #} {%set adazhaung%} 语句设置变量{{a}} 表达式{% if 2>1 %}控制语句以{%endif%}结尾 Jinja2支持使用“.”获取变量的属…

Python异常处理【侯小啾Python基础领航计划 系列(二十六)】

Python异常处理【侯小啾Python基础领航计划 系列(二十六)】 大家好,我是博主侯小啾, 🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔…

Tenda 路由器 uploadWewifiPic后台RCE漏洞复现

0x01 产品简介 腾达路由器是一款高效实用的路由器,致力于为家庭用户提供舒适、便捷、自然的智慧家庭体验。简单便捷的部署在家庭中,彻底解决家庭用户的网络接入问题。 0x02 漏洞概述 腾达路由器后台 uploadWewifiPic 路由存在命令执行漏洞,攻击者可利用漏洞执行任意命令获取…

汽车电子 -- 毫米波雷达

参看&#xff1a;自动驾驶感知——毫米波雷达 一、雷达分类 二、毫米波雷达信号频段 三、车载毫米波雷达的重要参数 常见参数 探测距离 &#xff08;车辆0.5m ~ 200m 行人0.5m ~ 70m&#xff09;距离向精度 &#xff08;0.15 m&#xff09;距离向分辨率 ( 0.5 m)测速范围…

施密特触发器

1、作用 简单来说&#xff0c;施密特触发器可以将模拟信号转变成数字信号 2、为什么不使用比较器将模拟信号转变成数字信号 当输入电平高于参考电压时&#xff0c;输出高电平&#xff1b;输入电压低于参考电压时&#xff0c;输出低电平。这样比较器也可以实现模拟信号转换成数…

CTF特训日记day3

复现一下RWCTF5th shellfind题目 题目描述如下&#xff1a; Hello Hacker. You dont know me, but I know you. I want to play a game. Heres what happens if you lose. The device you are watching is hooked into your Saturday and Sunday. When the timer in the back …

C++ Primer 第十六章 模板与泛型编程 重点解读

文章目录 1 定义模板1.1 类模板成员函数的实例化&#xff1a;1.2 在类代码内简化模板类名的使用&#xff1a;1.3 令模板自己的类型参数成为友元&#xff08;C11&#xff09;1.4 模板类型别名1.4.1 typedef1.4.2 为模板定义类型别名(C11) 1.5 函数模板与类模板的区别1.6 使用类的…

如何撰写How-To文章:7个高效步骤(新手SEOer向导)

How-To类型的文章在各种领域都非常受欢迎&#xff0c;因为它们直接回应了读者的需求和问题。因此&#xff0c;很多网站也会针对一些信息型的关键词写很多How-To文章吸引流量。 “How-To”类文章也是我最喜欢的一种内容类型。因为它比起其他大部分内容类型来讲要容易写很多。 …

java开发之个微机器人的实现

简要描述&#xff1a; 二次登录 请求URL&#xff1a; http://域名地址/secondLogin 请求方式&#xff1a; POST 请求头Headers&#xff1a; Content-Type&#xff1a;application/jsonAuthorization&#xff1a;login接口返回 参数&#xff1a; 参数名必选类型说明wcId…

Vue框架学习笔记——列表渲染:v-for

文章目录 前文提要代码正文 前文提要 本人仅做个人学习记录&#xff0c;如有错误&#xff0c;请多包涵 主要学习链接&#xff1a;尚硅谷Vue2.0Vue3.0全套教程丨vuejs从入门到精通 代码正文 <body><div id"box"><ul><li v-for"(p,index)…

印刷生产ERP有哪些?印刷生产ERP系统哪一个好用

印刷生产行业发展历史悠久&#xff0c;不同规模的印刷生产工厂有差异化的经营策略和管理侧重点&#xff0c;同时在日常经营过程中也会遇到多样化的管理难题。 有些企业在车间排期、库存盘点、生产流程优化、资源整合、成本核算等方面存在不少管理问题。同时也有不少印刷生产企…

Java异常机制入门详解(上)

Java异常机制入门详解 基础知识 什么是异常&#xff1f; 在Java语言中&#xff0c;异常就是代表程序出现的问题。异常的引入不是让我们以后不出异常&#xff0c;而是程序出了异常之后&#xff0c;该如何处理。如如下两段代码&#xff0c;会各抛出一个异常&#xff1a; int[…