【洛谷题单】暴力枚举(上)

【前情提要】

此文章包含洛谷题单的枚举题单,共14题,本篇7道题,主要分析思路,并通过这几道题目,进行总结有关枚举的内容。所以内容比较多,可以先收藏起来,慢慢看。

题单链接:暴力枚举https://www.luogu.com.cn/training/108

题目1

分析1

在一个n行m列的棋盘里,找一共有多少正方形和长方形。

而正方形和长方形都属于矩形,区别只有长宽长度的问题,那么可以一并按照矩形分析,当长宽相等时是正方形,否则是长方形。

再接着想,该如何算出棋盘里有多少矩形呢?

首先假设是一个1x2的矩形,把它当作一块积木,放入棋盘中,那么它可以横着放,也可以竖着放。

1. 当它横着放,一共有多少种可能性?(假设棋盘长为n,宽为m)

  • 当我们只关注宽时——发现一共有m-1个长度为2的地方,
  • 当只关注长时——一共有n个长度为1的地方

最终结果为n*m-1

2. 而竖着放同理。

我们可以大胆猜测,长为a宽为b的矩形一共有(n-a+1)*(m-b+1)

那么我们为了更保险一些,再举个例子,假设求3x3矩形的个数

1. 当它横着放,一共有多少种可能性?(假设棋盘长为n,宽为m)

  • 当我们只关注宽时——发现一共有m-2个长度为3的地方,
  • 当只关注长时——一共有n-2个长度为3的地方

最终结果为(n-2)*(m-2)

2. 由于是正方形,不需要看竖着的情况

基本正确,为了更严谨一些,可以再尝试举出类似例子。

那根据这个思路,我们可以进一步写出代码,注意范围,那么谈到范围时,我们就要想到假如横着竖着去考虑的话,从横着的1x2到竖着的2x1,假设长方向的设为i,宽方向的设为j

那么对应着i=1,j=2和i=2,j=1,两种情况

而i的范围为从1到n,j的范围为1到m,只需要在里面遍历就可以出现上面这两种情况,所以不需要再多考虑。

代码1

#include<bits/stdc++.h>using namespace std;long long ans,res;int main()
{int n,m;scanf("%d %d",&n,&m);for(int i=1;i<=n;i++){for(int j=1;j<=m;j++){if(i==j)//正方形{ans+=(n-i+1)*(m-i+1);}else{res+=(n-i+1)*(m-j+1);//求长方形,长宽方向已固定,所以不需要看纵向和横向结果  }}}cout << ans << " " << res << endl;return 0;
}

总结1

这题的核心点在于如何求出矩形数量,通常情况下可以多多列举几个例子,去分析,然后推出整体的公式。

题目2

对于 100% 的数据,n≤5000。 

分析2

题目意思是给你一个数字m,把10个数字(每个数字范围为1到3)的加和变成这个数字,并输出方案数和具体方案内容。

显而易见10个循环是不行的,超出时间复杂度了。

所以只能另辟蹊径。

用dfs(也就是深度优先遍历)

不懂的可以先看这篇(觉得麻烦也可以不看,下面会简单说明)——dp_背包问题(涉及dfs分析,记忆化搜索)_固定背包体积装物品总价值最大,运筹学问题-CSDN博客

只需要看dfs的部分即可

简单来说,就是先假设第一个数字为1,在这个基础上有三种选择,第二个数字有可能是1,2,3,我们先选择1再进行考虑第三个数字,直到考虑完10个数字.

假设最后结果为m则算是一种方案(然后遍历输入?),回溯到考虑第十个数字,这里我们选择2。

如果结果不为m,则这种方案不算,要去考虑第十个数字,选择2。

理论成立,下面就是代码了。

代码2

#include<iostream>
#include<algorithm>
#include<cstring>using namespace std;const int N=1e5+10;
int a[N][11],s[11];
int n;
int res;void dfs(int x,int p){if(x==10){if(p!=n){return;}for(int i=0;i<10;i++){a[res][i]=s[i];}res+=1;return;}s[x]=1;dfs(x+1,p+1);s[x]=2;dfs(x+1,p+2);s[x]=3;dfs(x+1,p+3);return;
}int main(){scanf("%d",&n);dfs(0,0);//0表示调料的总克数cout<<res<<endl;for(int i=0;i<res;i++){for(int j=0;j<10;j++){printf("%d ",a[i][j]);}printf("\n");}return 0;
}

总结2

这是一道简单的dfs题,按照正常递归思路思考回溯即可

题目3

分析

9个数字,组合成三个数A,B,C,满足一定的比例关系。

那么假如我们已经知道了A,则可以根据比例求出B和C,再去判断满足不满足每个数字只在A,B,C,中出现且仅出现一次的条件。

那么怎么去实现呢?

1. A是怎么遍历的

2. 怎么判断每个数字在A,B,C中有且仅出现一次

首先,A是由1到9这几位数字中抽出三个数字组合而成的。

A的第一位有9种可能性,第二位有除了第一位以外的其余8种可能性,第三位有7种可能性

假设我们嵌套遍历——A的每一位数字,把A弄出来之后,再计算B和C,再设置变量存储B和C的每一位数字,确保每一位都不相等——则输出A,B,C

假如没有输出(可以借用bool变量判断,刚开始定义为false如果输出了则该变量等于true,最后根据这个看是否输出No!!!)则输出No!!!

代码

#include<bits/stdc++.h>using namespace std;int main()
{double a,b,c;bool f=false;cin>>a>>b>>c;if(a==b||a==c||b==c){cout<<"No!!!";return 0;}b/=a;c/=a;for(int i=1;i<10;i++){for(int j=1;j<10;j++){for(int k=1;k<10;k++){if(i!=j&&i!=k&&j!=k){int n1=i*100+j*10+k;int n2=n1*b;int s1=n2%10;int s2=n2%100/10;int s3=n2/100;if(s1!=s2&&s1!=s3&&s2!=s3&&s1!=i&&s1!=j&&s1!=k&&s2!=i&&s2!=j&&s2!=k&&s3!=i&&s3!=j&&s3!=k&&n2<1000&&s1!=0&&s2!=0&&s3!=0){int n3=n1*c;int p1=n3%10;int p2=n3%100/10;int p3=n3/100;if(p1!=p2&&p1!=p3&&p2!=p3&&p1!=i&&p1!=j&&p1!=k&&p1!=s1&&p1!=s2&&p1!=s3&& p2!=i&&p2!=j&&p2!=k&&p2!=s1&&p2!=s2&&p2!=s3&& p3!=i&&p3!=j&&p3!=k&&p3!=s1&&p3!=s2&&p3!=s3&&n3<1000&&p1!=0&&p2!=0&&p3!=0){cout<<n1<<" "<<n2<<" "<<n3<<endl;f=true;}}}}}}if(!f){cout<<"No!!!";}return 0;
}

总结

这题主要是分析,分析出来如何做的写代码就简单了

题目4

分析

题目意思是给你n个数,从中选k个,加和,判断和是否为素数,如果是则种类加1

那么这题代码主要点在于——1. 从n个数中选k个,2 判断和是否为素数

分别考虑如何实现

1. 从n个数中选则k个,首先可以用for循环遍历取得k位数字,也可以用dfs函数,把n个数填在k个格子里面,每个数只能用一次。

2. 判断是否为素数,单开一个函数即可,从素数的定义入手,素数是指从1到本身,它只能%1和它本身时==0,为了简便,可以把范围从sum缩小到sqrt(sum)

理论上我们已经分析出做法了,那么下面就是具体的实施了

代码

#include<iostream>
#include<algorithm>
#include<cstring>
#include<cmath>using namespace std;int a[21];
int k,res,n,flag;
//bool s[21];
int startid;bool issu(int p)
{if (p < 2) return false;for (int i = 2; i <= sqrt(p); i++) {if (p % i == 0) return false;}return true;
}void dfs(int x)
{if(x==k){if(issu(res)){flag++;}return;}else{int start=startid;for(int i=start;i<n;i++){res+=a[i];startid=i+1;dfs(x+1);res-=a[i];startid=start;}}
}
int main()
{cin>>n>>k;for(int i=0;i<n;i++){cin>>a[i];}dfs(0);cout<<flag<<endl;return 0;
}

总结

代码中有个重要的点——》就是在dfs中如何防止元素重复,也就是这个元素用过了,如何防止下次不再用。我们把这部分的代码拿出来分析

首先定义了

int start=startid;
for(int i=start;i<n;i++)
{res+=a[i];startid=i+1;dfs(x+1);res-=a[i];startid=start;
}//把dfs函数参数设置为三个
void dfs(int e,int sum,int x)//x表示下一回的开始
{if(e==k){if(isPrime(sum)){res++;}return;}for(int i=x;i<n;i++){dfs(e+1,sum+s[i],i+1);//下一回从i+1开始}return;
}

 这个部分建议记忆,在很多题目中也可能会用到。

题目5

分析

这个题说的是从n个元素中抽出r个元素,输出所有组合,(格式是每个组合数字要占三个字符,用到setw(),或者直接用printf格式化输出)

我们来看如何去写,

依旧是假设有r个位置,要把n个元素不重复的填入进去,每个位置有多种选择,可以用dfs来实现

代码(dfs)

#include<iostream>
#include<algorithm>
#include<iomanip>using namespace std;const int N=21;
int s[N];
int n,r;void dfs(int e,int f,int x)
{if(e==r){for(int i=0;i<r;i++){cout<<setw(3)<<s[i];}cout<<endl;return;}for(int i=f;i<r;i++){for(int j=x;j<=n;j++){s[i]=j;if(s[i-1]<s[i]){dfs(e+1,f+1,j+1);//s[i]=0;//为什么不用还原?因为下一次会被覆盖}}}
}int main()
{scanf("%d%d",&n,&r);dfs(0,0,1);return 0;
}

总结

这个依旧用到了上个问题的不重复写入的方法,但这道题目和上一题不一样的是它需要把每次的结果存入数组中,所以需要再加一个for循环,但是为了不让数组每次遍历都从头开始,再设置一个参数,表示数组的位置。

题目6

分析

这题就是直接给你一共数,输出1到这个数的全排列。

有两种方法

1. 调用库函数next_permutation

2. 自己手写全排列函数

根据这个方法,我们依次分析一下

1. 库函数next_permutation(),里面传入两个参数,第一个是数组的首地址,第二个是数组的末地址,和sort函数差不多,它返回这个数组的下一个全排列

2. 假如自己手写全排列函数,相当于有n个位置,要把n个数填入这几个位置上,每个位置有不止一种选择,用dfs来实现,和上一题差不多,但比那个要简单一些

注意,输出时的元素要占5个位置,用上一题的setw()函数,记得写头文件#include<iomanip>

代码(next_permutation)

#include<iostream>
#include<algorithm>
#include<iomanip>using namespace std;int main()
{int n,l=1;scanf("%d",&n);int s[n];for(int i=1;i<=n;i++){s[i]=i;l*=i;}//全排列一共n!种for(int i=1;i<=l;i++){for(int j=1;j<=n;j++){cout<<setw(5)<<s[j];}cout<<endl;next_permutation(s+1,s+n+1);}return 0;
}

 

代码(dfs)

#include<bits/stdc++.h>using namespace std;int s[10];
bool a[10];
int n;
int res=1,ans;void dfs(int e)
{if(e>n){for(int i=1;i<=n;i++){cout<<setw(5)<<s[i];}cout<<endl;return;}for(int i=1;i<=n;i++){if(!a[i]){a[i]=true;s[e]=i;dfs(e+1);a[i]=false;}}
}int main()
{scanf("%d",&n);int m=n;while(m!=1){res*=m;m--;}dfs(1);return 0;
}

总结

这里用了另一种防止填入数字重复的方法,只需要定义一个长度和int数组一样大的布尔数组,初始值为false,如果没用过了则可以把它存入int数组并,并更新为true,遍历下一个dfs,同时回溯把刚才的true变为false

题目7

 

分析

这个题目稍微有些复杂,就是说会给你n个数字,以及要在这个数字组合成的外星文上加的数

主要问题在于如何把这n个数字加m后变成另外n个数字,这个过程是怎样运作的

我们主要观察这个部分:

这是只有三个手指的时候,相当于123的全排列,而且是按照顺序的,所以很自然地想到了用全排列那题的方法,next_permutation()

代码

#include<bits/stdc++.h>using namespace std;int main()
{int n,m;scanf("%d",&n);scanf("%d",&m);int a[n];for(int i=0;i<n;i++){scanf("%d",&a[i]);}for(int i=1;i<=m;i++){next_permutation(a,a+n);}for(int i=0;i<n;i++){printf("%d ",a[i]);}return 0;
}

总结

这题主要是刚开始不太好想到,要善于观察那手指的数字,从中发现规律。 

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

JVM类加载过程详解

文章目录 前言1.加载2.链接验证文件格式验证元数据验证字节码验证符号引用验证 准备解析 3.初始化4.类卸载 前言 类从被加载到虚拟机内存中开始到卸载出内存为止&#xff0c;它的整个生命周期可以简单概括为 7 个阶段&#xff1a;加载&#xff08;Loading&#xff09;、验证&a…

python之并发编程

并发编程介绍 串行、并行与并发的区别 进程、线程、协程的区别 1. 进程 (Process) 定义&#xff1a;进程是操作系统为运行中的程序分配的基本单位。每个进程都有独立的地址空间和资源&#xff08;如内存、文件句柄等&#xff09;。特点&#xff1a; 进程是资源分配的基本单位…

批量优化与压缩 PPT,减少 PPT 文件的大小

我们经常能够看到有些 PPT 文档明明没有多少内容&#xff0c;但是却占用了很大的空间&#xff0c;存储和传输非常的不方便&#xff0c;这时候通常是因为我们插入了一些图片/字体等资源文件&#xff0c;这些都可能会导致我们的 PPT 文档变得非常的庞大&#xff0c;今天就给大家介…

centos 7 LVM管理命令

物理卷&#xff08;PV&#xff09;管理命令 pvcreate&#xff1a;用于将物理磁盘分区或整个磁盘创建为物理卷。 示例&#xff1a;sudo pvcreate /dev/sdb1 解释&#xff1a;将 /dev/sdb1 分区创建为物理卷。 pvdisplay&#xff1a;显示物理卷的详细信息&#xff0c;如大小、所属…

b站视频提取mp4方案

引言 对于b站视频&#xff0c;有些视频是不能提取字幕的&#xff0c;所以我们想把对应的视频下载下来&#xff0c;然后进行对应的本地处理&#xff0c;获得所需的自由处理&#xff0c;吞食视频。 整体思路 下载b站客户端 ----> 把缓存路径修改------> 下载所需视频---…

springboot在feign和线程池中使用TraceId日志链路追踪(最终版)-2

文章目录 简述问题feign调用时给head加入traceIdFeignConfig配置FeignConfig 局部生效feign拦截器和配置合并为一个文件&#xff08;最终版&#xff09;feign异步调用拦截器配置[不常用] 使用TTL自定义线程池为什么需要TransmittableThreadLocal&#xff1f; 总结参考和拓展阅读…

MySQL数据库单表与多表查询

一.单表查询 1.创建用于数据查询的数据库表 CREATE TABLE worker (部门号 int(11) NOT NULL,职工号 int(11) NOT NULL,工作时间 date NOT NULL,工资 float(8,2) NOT NULL,政治面貌 varchar(10) NOT NULL DEFAULT 群众,姓名 varchar(20) NOT NULL,出生日期 date NOT NULL,PRIM…

海外紧固件市场格局与发展趋势研究报

一、引言 紧固件作为各类机械装备、建筑结构以及电子设备中不可或缺的基础性零部件&#xff0c;在国民经济的各个领域都有着广泛应用。其市场动态与全球经济发展态势以及各行业的兴衰紧密相连。在全球化进程不断加速、产业分工日益精细的大背景下&#xff0c;深入研究海外紧固…

【多学科稳定EI会议大合集】计算机应用、通信信号、电气能源工程、社科经管教育、光学光电、遥感测绘、生物医学等多学科征稿!

在当今科技高速发展的时代&#xff0c;多学科领域的学术交流与融合显得尤为重要。以下是稳定EI会议合集&#xff0c;涵盖计算机、信息通信、电气能源、社科经管教育、光学遥感、生物医学等多个学科领域。 会议皆已通过国际知名出版社出版审核&#xff0c;EI检索稳定&#xff0…

【深度学习新浪潮】展平RVQ技术详解

展平 RVQ(Flattened Residual Vector Quantization)是一种基于矢量量化(Vector Quantization, VQ)的技术,主要用于高效地表示和压缩数据(例如图像、音频或文本嵌入)。它结合了**残差矢量量化(Residual Vector Quantization, RVQ)**的思想与“展平”操作,从而进一步优…

【第23节】windows网络编程模型(WSAEventSelect模型)

目录 引言 一、WSAEventSelect模型概述 二、 WSAEventSelect模型的实现流程 2.1 创建一个事件对象&#xff0c;注册网络事件 2.2 等待网络事件发生 2.3 获取网络事件 2.4 手动设置信号量和释放资源 三、 WSAEventSelect模型伪代码示例 四、完整实践示例代码 引言 在网…

LlamaFactory部署及模型微调【win10环境】

1.Llama-Factory简介 LLaMA-Factory&#xff0c;全称 Large Language Model Factory&#xff0c;旨在简化大模型的微调过程&#xff0c;帮助开发者快速适应特定任务需求&#xff0c;提升模型表现。它支持多种预训练模型和微调算法&#xff0c;适用于智能客服、语音识别、机器翻…

Jmeter简介、学习目标及安装启动

1. 简介 JMeter 是 Apache 组织使用 Java 开发的一款测试工具&#xff1a;可以用于对服务器、网络或对象模拟巨大的负载&#xff1b;通过创建带有断言的脚本来验证程序是否能返回期望的结果。 1&#xff09;优点&#xff1a;开源、免费&#xff1b;跨平台&#xff1b;支持多协…

无参数读文件和RCE

什么是无参数&#xff1f; 无参数&#xff08;No-Argument&#xff09;的概念&#xff0c;顾名思义&#xff0c;就是在PHP中调用函数时&#xff0c;不传递任何参数。我们需要利用仅靠函数本身的返回值或嵌套无参数函数的方式&#xff0c;达到读取文件或远程命令执行&#xff0…

细胞内与细胞间网络整合分析!神经网络+细胞通讯,这个单细胞分析工具一箭双雕了(scTenifoldXct)

生信碱移 细胞间-细胞内通讯网络分析 scTenifoldXct&#xff0c;一种结合了细胞内和细胞间基因网络的计算工具&#xff0c;利用 scRNA-seq 数据检测细胞间相互作用。 单细胞 RNA 测序&#xff08;scRNA-seq&#xff09;能够以稳健且可重复的方式同时收集数万个细胞的转录组信息…

怎么处理 Vue 项目中的错误的?

一、错误类型 任何一个框架,对于错误的处理都是一种必备的能力 在Vue 中,则是定义了一套对应的错误处理规则给到使用者,且在源代码级别,对部分必要的过程做了一定的错误处理。 主要的错误来源包括: 后端接口错误代码中本身逻辑错误二、如何处理 后端接口错误 通过axi…

05.AI搭建preparationの(transformers01)BertTokenizer实现分词编码

一、下载 bert-base-chinese镜像下载 二、简介作用&#xff1a; 模型每个参数占用的字节大小模型大小模型大小层数头数GPT-14 个字节的 FP32 精度浮点数117M446MB1212GPT-22 个字节的 FP161.5亿到1.75亿0.5GB到1.5GB4816GPT-32 个字节的 FP161.75万亿&#xff08;17500亿&a…

工业4G路由器赋能智慧停车场高效管理

工业4G路由器作为智慧停车场管理系统通信核心&#xff0c;将停车场内的各个子系统连接起来&#xff0c;包括车牌识别系统、道闸控制系统、车位检测系统、收费系统以及监控系统等。通过4G网络&#xff0c;将这些系统采集到的数据传输到云端服务器或管理中心&#xff0c;实现信息…

git 基础操作

1. git 的安装 与 卸载 1.1. git 的安装 判断是否安装 git git --version 安装 git: centos: sudo yum -y install git ubuntu: sudo apt-get install git -y windows: 3.安装git和图形化界面工具_哔哩哔哩_bilibili 1.2. git 的卸载 判断是否安装 git git --version…

【计算机网络】计算机网络协议、接口与服务全面解析——结合生活化案例与图文详解

协议、接口与服务 导读一、协议1.1 定义1.2 组成 二、接口三、服务3.1 定义3.2 服务与协议的区别3.3 分类3.3.1 面向连接服务于无连接服务3.3.2 可靠服务和不可靠服务3.3.3 有应答服务和无应答服务 结语 导读 大家好&#xff0c;很高兴又和大家见面啦&#xff01;&#xff01;…