当前位置: 首页 > news >正文

【Acwing166】数独(dfs+剪枝+位运算)超级详细题解!

本题思路来源于acwing算法提高课

题目描述

看本文需要准备的知识

1.dfs算法基本思想

2.位运算基础

3.对剪枝这个名词的大概了解

剪枝优化+位运算优化

常见四种剪枝策略

首先考虑这道题的搜索顺序,很明显,可以随意选择一个空格子,分支为这个空格子可以填入的所有数字,然后对于每个分支,可以再随意选择一个空格子,继续进行上述步骤达成递归,这种搜索顺序是一定能够把每一种情况不漏地搜索到

下面考虑优化的策略:

第一个优化,优化搜索顺序,可以考虑一下,什么情况下,搜索的分支较少呢?显然是对于那些可以填的数字合法情况比较少的空格,所以我们再找下一个空格时,就优先选择这类的空格

上面的搜索顺序保证了不会有冗余,所以第二个剪枝策略用不上

第二个优化,可行性剪枝,就是说在遍历过程当中,只考虑那些合法的数字分支,即在那个空格的行、列以及九宫格上面不能有数字重复

最优性剪枝也是用不上的,因为这里面只要找到一个合法解就行了,不存在最优解的区分

第三个优化是位运算,用来做两件事情:

1.用一个9位的01串表示一行或一列或一个九宫格里面的填充情况,0表示已经填充,1表示没有填充,举一个例子,row[2]=000111010表示第二行已经用过了9,8,7,3,1,列col和九宫格cell同理,那么对于一个坐标为(x,y)的空格,怎么知道可以填哪些数字呢?只需要把对应的row、col、cell进行与运算,看一下1出现了第几位上,那么就可以填几

2.lowbit优化

lowbit是什么?是一个运算,比如lowbit(x)=x&-x

lowbit可以算出什么?比如10101可以得到1,100100可以得到100,11000可以得到1000(注意上面的都是二进制数,即得到最低位1的位置)

有了lowbit之后,对于一个空格,假设我们通过上面二进制表示的行、列、九宫格的与运算得到了一个01串:101001010,这个01串有4个1,如果直接遍历,每次都要9次,但是如果用上lowbit,只需要遍历4次即可:

lowbit(101001010)=10,第2位的1,所以可以放2

lowbit(101001000)=1000,第4位的1,所以可以放4

依次类推......

详细过程

讲解了本题的优化策略,下面来详细介绍,这道题的实现细节

首先定义6个数组:

其中三个为int row[N],col[N],cell[N][N],存放对应位置的状态

第四个是int ones[1<<N],表示某一个数的二进制表示里面有几个1

第五个是int log2[1<<N],表示某一个数的以2为底的对数,因为使用lowbit之后得到的是2的k次幂,而这个k才是我们想要的(代表1的位置),所以我们预处理这个数组,方便后续使用

第六个就是char str[100],代表所有的格子内容,包括数字和小数点(表示暂时没有填充)这两种情况

然后再写四个辅助函数,分别是init,draw,get_state,lowbit

init:初始化所有格子,暂时全部没有填过数字

draw:在(x,y)这个格子上面填上数字t(is_set==true),或者去掉数字t(is_set==false)

get_state:得到(x,y)上的行、列、九宫格的状态交集01串

lowbit:上面已经讲解过了

然后我们来说一下main函数的内容:

对于每一个样例,init初始化,然后遍历输入的str,对方格进行填充,如果遇到’.’那么就记录一下,最终统计暂未填充的格子总数,最后调用dfs,最后输出str即可

最后我们说dfs如何写:

首先参数cnt代表还剩几个空格没有填数,当cnt==0时,直接返回true即可,表示已经全部填充完毕。

然后,寻找分支数最少的空格(搜索顺序优化)

找到之后,通过get_state函数得到01串,然后利用lowbit去得到这个01串中1的每个位置,就是一个新的分支,这个遍历之后返回false保证函数代码的完整性

完整代码

#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
const int N=9,M=1<<N;
int row[N],col[N],cell[N][N];
int ones[M],log2_map[M];
char str[100];
void init()
{for(int i=0;i<N;i++)row[i]=col[i]=(1<<N)-1;for(int i=0;i<N/3;i++){for(int j=0;j<N/3;j++)cell[i][j]=(1<<N)-1;}
}
void draw(int x,int y,int t,bool is_set)
{if(is_set)str[x*N+y]=t+'1';else str[x*N+y]='.';int r=1<<t;if(!is_set)r=-r;row[x]-=r;col[y]-=r;cell[x/3][y/3]-=r;
}
int lowbit(int x)
{return x&-x;
}
int get_state(int x,int y)
{return row[x]&col[y]&cell[x/3][y/3];
}
bool dfs(int cnt)
{if(!cnt)return true;int minx=10;int x,y;for(int i=0;i<N;i++){for(int j=0;j<N;j++){if(str[i*N+j]=='.'){int state=get_state(i,j);if(ones[state]<minx){minx=ones[state];x=i,y=j;}}}}int state=get_state(x,y);for(int i=state;i;i-=lowbit(i)){int t=log2_map[lowbit(i)];draw(x,y,t,true);if(dfs(cnt-1))return true;draw(x,y,t,false);}return false;
}
int main()
{for(int i=0;i<N;i++)log2_map[1<<i]=i;for(int i=0;i<1<<N;i++)for(int j=0;j<N;j++)ones[i]+=(i>>j)&1;while(cin>>str,str[0]!='e'){init();int cnt=0;for(int i=0,k=0;i<N;i++){for(int j=0;j<N;j++,k++){if(str[k]!='.'){draw(i,j,str[k]-'1',true);}else cnt++;}}dfs(cnt);cout<<str<<endl;}return 0;
}

相关文章:

【Acwing166】数独(dfs+剪枝+位运算)超级详细题解!

本题思路来源于acwing算法提高课 题目描述 看本文需要准备的知识 1.dfs算法基本思想 2.位运算基础 3.对剪枝这个名词的大概了解 剪枝优化位运算优化 常见四种剪枝策略 首先考虑这道题的搜索顺序&#xff0c;很明显&#xff0c;可以随意选择一个空格子&#xff0c;分支为这…...

Docker Swarm 集群搭建

Docker Swarm Mode Docker Swarm 集群搭建 Docker Swarm 节点维护 Docker Service 创建 1.准备主机 搭建一个 docker swarm 集群&#xff0c;包含 5 个 swarm 节点。这 5 个 swarm 节点的 IP 与暂 时的角色分配如下&#xff08;注意&#xff0c;搭建完成后会切换角色&#xff…...

Mac 开机提示Google LLC 注册 无法登录进入系统

Google LLC 会在电脑启动时提示如下弹窗&#xff0c;并要求登录谷歌账户进行验证 此时很明显没有用来进行验证的账号&#xff0c;所以需要关掉这个验证程序 从日志里面可以看到LLC启动了一个Tiny.app的程序 只需要想办法把这个程序删掉即可 关机 按住 Command R 开机 进入R…...

excel单元格各种组合求和

单元格如果连续选择的话使用冒号&#xff0c;不是连续选择使用逗号&#xff1b;sum(A1:A4)表示对A1到A4求和&#xff1b;sum(A1,A4)表示求A1A4的和&#xff1b; 如下图&#xff0c;求斜线上四个单元格的和&#xff0c;结果见下图&#xff1b; 求A列和C列全部单元格的和&#x…...

SysTick—系统定时器

SysTick 简介 SysTick—系统定时器是属于CM3内核中的一个外设&#xff0c;内嵌在NVIC中。系统定时器是一个24bit 的向下递减的计数器&#xff0c;计数器每计数一次的时间为1/SYSCLK&#xff0c;一般我们设置系统时钟SYSCLK 等于72M。当重装载数值寄存器的值递减到0的时候&#…...

ATPCS:ARM-Thumb程序调用的基本规则

为了使单独编译的c文件和汇编文件之间能够互相调用&#xff0c;需要制定一系列的规则&#xff0c;AAPCS就是ARM程序和Thumb程序中子程序调用的基本规则。 1、ATPCS概述 ATPCS规定了子程序调用过程中寄存器的使用规程、数据站的使用规则、参数的传递规则。为了适应一些特殊的需…...

Swift 判断 A B 两个时间是不是同一天,A 是不是 B 的昨天

1. 今天要做这个效果&#xff08;在时间旁边显示今天&#xff0c;昨天&#xff09; 2. Preview 3. Code: // 添加 今天 昨天 func show_today_yesterday(d: Date Date()) -> String {let calendar Calendar.currentlet today: Date Date()if calendar.isDate(today, inS…...

华为OD 高效的任务规划(200分)【java】A卷+B卷

华为OD统一考试A卷+B卷 新题库说明 你收到的链接上面会标注A卷还是B卷。目前大部分收到的都是B卷。 B卷对应20022部分考题以及新出的题目,A卷对应的是新出的题目。 我将持续更新最新题目 获取更多免费题目可前往夸克网盘下载,请点击以下链接进入: 我用夸克网盘分享了「华为O…...

使用VGG框架实现从二分类到多分类

一.数据集的准备 与之前的不同&#xff0c;这一次我们不使用开源数据集&#xff0c;而是自己来制作数据集。重点需要解决的问题是对数据进行预处理&#xff0c;如每一个图片的大小均不同&#xff0c;需要进行resize&#xff0c;还需要对每一张图片打标签等操作。 数据集文件 …...

Ubuntu服务器配置qq邮箱发送信息

效果&#xff1a; 此处设置的是自己给自己发送&#xff0c;配合linux的cron实现定时触发发送事件的效果 实现过程&#xff1a; 安装邮箱客户端Postfix sudo apt-get install postfix配置Postfix&#xff1a;编辑Postfix的主要配置文件 /etc/postfix/main.cf&#xff0c;并在…...

HTML读书笔记

HTML的读书笔记 概述 Jack 2023.10.23 参考网站&#xff1a; w3school 在线教程 HTML 头部 | 菜鸟教程 本教程已教你如何使用 HTML 创建站点。 HTML 是一种在 Web 上使用的通用标记语言&#xff08;并不是类似Python一样的编程语言&#xff09;。HTML 允许你格式化文本&…...

初识Java

一、Java语言概述 1.1 Java是什么 Java是一种优秀的程序设计语言&#xff0c;它具有令人赏心悦目的语法和易于理解的语义 不仅如此&#xff0c;Java还是一个有一系列计算机软件和规范形成的技术体系&#xff0c;这个技术体系提供了完整的用于软件开发和跨平台部署的支持环境&a…...

bootstrap.properties中配置Nacos

bootstrap.properties用于在Spring Boot应用程序启动阶段加载外部配置 优先级高&#xff1a;在应用程序启动时首先加载&#xff0c;用于配置应用程序的基础设置&#xff0c;如配置数据源、日志、配置服务器 外部配置&#xff1a;加载外部配置源&#xff08;如远程配置服务器&a…...

【CVPR 2023】Diffusion Models高分辨率长视频生成 Align your Latents

Diffusion Models专栏文章汇总:入门与实战 前言:CVPR 2023年的工作《Align your Latents: High-Resolution Video Synthesis with Latent Diffusion Models》实现了高帧率高分辨率长视频生成,并在保持时间一致性上做了很多工作。这篇博客详细解读一下背后的原理,并总结一下…...

[Linux 基础] make、Makefile自动化构建代码工具

文章目录 1、make与Makefile是什么2、为什么要有make与Makefile3、怎么实现一个Makefile文件3.1 如何编写Makefile文件3.1.1 依赖关系3.1.2 依赖方法 3.2 如何清理项目3.2.1 如何编写3.2.2 clean详解 3.3 make的使用3.4 原理3.4.1 查看文件修改时间 1、make与Makefile是什么 m…...

vue3结合Cesium加载倾斜摄影3dtiles

这篇文章主要是为了记录加载3dtiles时模型与地形有时候存在一些高度上的差异&#xff0c;为此将解决方法做一个记录&#xff0c;便于其他读者使用。 加载倾斜摄影3dtitle //加载倾斜摄影图像 function init3Dtiles() {const tileSet new Cesium3DTileset({url: "http://1…...

面对DDoS和APT攻击,我们该如何有效防御?

关于DDoS&#xff08;Distributed Denial of Service&#xff09;分布式拒绝服务攻击&#xff0c;是指攻击者通过技术手段&#xff0c;在很短的时间内对目标攻击网站发出大量请求&#xff0c;极大地消耗相关网站的主机资源&#xff0c;导致其无法正常服务。 打个比方来说&#…...

【前端学习】—Vue生命周期(十七)

【前端学习】—Vue生命周期&#xff08;十七&#xff09; 一、Vue生命周期 二、Vue父子组件生命周期调用顺序 三、Vue中在哪个生命周期内调用异步请求...

ant的Path-like结构

ant可以使用path和classpath结构指明路径。path和classpath可以包含内嵌的元素&#xff0c;类似下面的通用形式&#xff1a; <classpath><pathelement path"${classpath}"/><pathelement location"lib/helper.jar"/> </classpath>…...

Java设计模式之组合模式

比如在实现一个文件管理系统时&#xff0c;对于客户端来说&#xff0c;如果需要区分文件与文件夹的使用&#xff0c;会比较麻烦&#xff0c;使用组合模式可以在使用不同对象时使用方法保持一致性。 定义 又名部分整体模式&#xff0c;是用于把一组相似的对象当作一个单一的对…...

IDEA运行Tomcat出现乱码问题解决汇总

最近正值期末周&#xff0c;有很多同学在写期末Java web作业时&#xff0c;运行tomcat出现乱码问题&#xff0c;经过多次解决与研究&#xff0c;我做了如下整理&#xff1a; 原因&#xff1a; IDEA本身编码与tomcat的编码与Windows编码不同导致&#xff0c;Windows 系统控制台…...

【Axure高保真原型】引导弹窗

今天和大家中分享引导弹窗的原型模板&#xff0c;载入页面后&#xff0c;会显示引导弹窗&#xff0c;适用于引导用户使用页面&#xff0c;点击完成后&#xff0c;会显示下一个引导弹窗&#xff0c;直至最后一个引导弹窗完成后进入首页。具体效果可以点击下方视频观看或打开下方…...

Docker 离线安装指南

参考文章 1、确认操作系统类型及内核版本 Docker依赖于Linux内核的一些特性&#xff0c;不同版本的Docker对内核版本有不同要求。例如&#xff0c;Docker 17.06及之后的版本通常需要Linux内核3.10及以上版本&#xff0c;Docker17.09及更高版本对应Linux内核4.9.x及更高版本。…...

ssc377d修改flash分区大小

1、flash的分区默认分配16M、 / # df -h Filesystem Size Used Available Use% Mounted on /dev/root 1.9M 1.9M 0 100% / /dev/mtdblock4 3.0M...

工程地质软件市场:发展现状、趋势与策略建议

一、引言 在工程建设领域&#xff0c;准确把握地质条件是确保项目顺利推进和安全运营的关键。工程地质软件作为处理、分析、模拟和展示工程地质数据的重要工具&#xff0c;正发挥着日益重要的作用。它凭借强大的数据处理能力、三维建模功能、空间分析工具和可视化展示手段&…...

基础测试工具使用经验

背景 vtune&#xff0c;perf, nsight system等基础测试工具&#xff0c;都是用过的&#xff0c;但是没有记录&#xff0c;都逐渐忘了。所以写这篇博客总结记录一下&#xff0c;只要以后发现新的用法&#xff0c;就记得来编辑补充一下 perf 比较基础的用法&#xff1a; 先改这…...

【决胜公务员考试】求职OMG——见面课测验1

2025最新版&#xff01;&#xff01;&#xff01;6.8截至答题&#xff0c;大家注意呀&#xff01; 博主码字不易点个关注吧,祝期末顺利~~ 1.单选题(2分) 下列说法错误的是:&#xff08; B &#xff09; A.选调生属于公务员系统 B.公务员属于事业编 C.选调生有基层锻炼的要求 D…...

微信小程序云开发平台MySQL的连接方式

注&#xff1a;微信小程序云开发平台指的是腾讯云开发 先给结论&#xff1a;微信小程序云开发平台的MySQL&#xff0c;无法通过获取数据库连接信息的方式进行连接&#xff0c;连接只能通过云开发的SDK连接&#xff0c;具体要参考官方文档&#xff1a; 为什么&#xff1f; 因为…...

如何在最短时间内提升打ctf(web)的水平?

刚刚刷完2遍 bugku 的 web 题&#xff0c;前来答题。 每个人对刷题理解是不同&#xff0c;有的人是看了writeup就等于刷了&#xff0c;有的人是收藏了writeup就等于刷了&#xff0c;有的人是跟着writeup做了一遍就等于刷了&#xff0c;还有的人是独立思考做了一遍就等于刷了。…...

Java线上CPU飙高问题排查全指南

一、引言 在Java应用的线上运行环境中&#xff0c;CPU飙高是一个常见且棘手的性能问题。当系统出现CPU飙高时&#xff0c;通常会导致应用响应缓慢&#xff0c;甚至服务不可用&#xff0c;严重影响用户体验和业务运行。因此&#xff0c;掌握一套科学有效的CPU飙高问题排查方法&…...