dfs 判重Sequence one——hdu 2610

news2024/10/10 3:06:56

目录

前言

搜索算法判重

        map判重

        set判重

Sequence one

问题描述

输入

输出

数据范围

样例

问题分析

重构dfs参数

递减,不重复

去重的优化

最终代码


前言

搜索算法判重

        搜索算法判重有很多种方法,常见的有两种,map判重和set判重

#include<set>
#include<map>
using namespace std;

        map判重

	string s;
	//map判重
	map<string, bool>mp;
	if (!mp[s]) {
		mp[s] = true;
		//dfs or bfs
	}

        set判重

	string s;
	//set判重
	set<string>vis;
	if (vis.count(s) == 0) {
		vis.insert(s);
		//dfs or bfs
	}

但本题这两种判重都不是最佳   

    

Sequence one

问题描述

        给定一个序列,要求该序列前p个不递减的子序列,如果不足p个则输出所有

输入

        有多个测试,每个测试第一行输入两个整数n,p,分别代表序列元素个数,以及要求输出个数,第二行输入n个整数

输出

        对于每个测试输出前p个不递减的序列

数据范围

        1<n<=1000      1<p<=10000   每个整数不大于2^{31}

样例

问题分析

        本题完全可以看作一个加了很多限制的全排列问题,先附上全排列代码

//默认大家都会哈,这个应该是最简单的dfs了
void dfs(int s, int t) {
	if (s == t) {
		for (int i = 0; i < t; i++) {
			cout << b[i] << " ";	
		}
		cout << endl;
		return;
	}
	for (int i = 0; i < t; i++) {
		if (!vis[i]) {
			vis[i] = true;
			b[s] = a[i];
			dfs(s + 1, t);
			vis[i] = false;
		}
	}
}

        之后我们要做的就是对这段代码加上各种剪枝,使得它符合题目要求

重构dfs参数

        我们先考虑如何选择dfs函数参数问题,本题要求输出的是子序列,那么输出长度就是需要变化的,我吗命名为sublen,那么至少还需要一个参数代表我们当前递归层已经拼好的子序列长度为多少,我们命名为now_len,之后就是题目要求求不递减的子序列,那么每拼好一个整数,应该是从下一个数字开始拼,那么我们还需要一个参数,表示当前位置,命名为now_pos。到此我们就已经搭建好了基本的代码框架

void dfs(int sublen, int now_len, int now_pos){

    return;
}


int main(){
    for (int i = 1; i <= n; i++) {
		dfs(i, 0, 1);
	}
}

递减,不重复

        题目说到要求递减的序列,那么就可以再每层递归前加上限制条件,而且需要使得每次生成的序列不再重复(重复的原因是因为序列中有重复的元素),那么就可以在输出序列之前判重,完整代码长这样:

//先写个单次输入的
#include<map>
#include<iostream>
using namespace std;
int n, p;
int cnt = 0;
int a[1010];
int b[1010];
map<string, bool>mp;
bool vis[1010];

void dfs(int sublen,int now_len,int now_pos) {
	if (cnt == p) {
		return;
	}
	if (now_len == sublen) {
		string s;
		for (int i = 0; i < sublen; i++) {
			s += b[i];
		}
		//map判重
		if (!mp[s]) {
			for (int i = 0; i < sublen-1; i++) {
				cout << b[i] << " ";
			}
			if (sublen - 1 >= 0) {
				cout << b[sublen - 1] << endl;
			}
			cnt++;
			mp[s] = true;
		}
		return;
	}
	for (int i = now_pos; i <= n; i++) {
		if (!vis[i] &&  (now_len == 0 || b[now_len - 1] <=a[i])) {  //保证序列递增
			vis[i] = true;
			b[now_len] = a[i];
			dfs(sublen, now_len+1,i+1);
			//回溯
			vis[i] = false;
		}
	}
}


int main() {
	cin >> n >> p;
	for (int i = 1; i <=n; i++) {
		cin >> a[i];
	}
	for (int i = 1; i <= n; i++) {
		dfs(i,0,1);
	}
	return 0;
}

去重的优化

        当时我也想着就这样就可以结束了,但还是超时,服了,之后才知道,这里的去重其实是可以优化的,仔细看过dfs原理图的伙伴就知道,其实dfs原理是以一个元素为首,然后不断递归去找子序列,本题导致重复的原因就是两次使用了同一个数值的元素为首进行dfs(注意我说的是同一个数值,不是同一个数)

画的有点丑,忽略

那就只需要对每层dfs的队首做一次判断即可(注意每层dfs队首都会更新),这样如果序列中有重复的元素就可以去重

f代表front——队首

最终代码

#include<iostream>
#include<set>
#include<map>
using namespace std;
int n, p;
int cnt = 0;
int a[1010];
int b[1010];
bool vis[1010];

bool check(int a_ed, int a_i) {
	for (int i = a_ed; i < a_i; i++) {
		if (a[i] == a[a_i]) return false;
	}
	return true;
}

void dfs(int sublen, int now_len, int now_pos) {
	if (cnt == p) {
		return;
	}
	if (now_len == sublen) {
		for (int i = 0; i < sublen-1; i++) {
			cout << b[i] << " ";
		}
		if (sublen - 1 >= 0) {
			cout << b[sublen - 1] << endl;
		}
		cnt++;
		
		return;
	}
	for (int i = now_pos; i <= n; i++) {
		if (!vis[i] && (now_len == 0 || b[now_len - 1] <= a[i])) {
			if (now_len == 0) {
				if (!check(1, i)) continue;
			}
			if (now_len != 0) {
				if (!check(now_pos, i))continue;
			}
			vis[i] = true;
			b[now_len] = a[i];
			dfs(sublen, now_len + 1, i + 1);
			vis[i] = false;
		}
	}
}

int main() {
	while (~scanf_s("%d %d", &n, &p)) {
		for (int i = 1; i <= n; i++) {
			cin >> a[i];
		}
		cnt = 0;
		for (int i = 1; i <= n; i++) {
			dfs(i, 0, 1);
		}
		cout << endl;
	}
	return 0;
}

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

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

相关文章

模运算和快速幂

文章目录 模运算快速幂 模运算 模运算是大数运算中的常用操作。如果一个数太大&#xff0c;无法直接输出&#xff0c;或者不需要直接输出&#xff0c;则可以对它取模&#xff0c;缩小数值再输出。取模可以防止溢出&#xff0c;这是常见的操作。 取模运算一般要求a和m的符号一…

VCI_VBDSP使用教程-服务站

VCI_VBDSP使用教程-服务站 VBDSP软件压缩包请点击下载&#xff1a;(备注&#xff1a;将VBDSP软件压缩包做一个下载连接&#xff0c;放到此处) 教程视频&#xff1a;https://www.bilibili.com/video/BV19eHpeeEiz/?spm_id_from333.999.0.0&vd_source224b4434f72960113bc97…

数组的定义与使用(二)

2. 数组是引用类型 2.1初识JVM的内存分布 内存是一段连续的存储空间&#xff0c;主要用来存储程序运行时数据的。比如&#xff1a; 程序运行时代码需要加载到内存程序运行产生的中间数据要存放在内存程序中的常量也要保存有些数据可能需要长时间储存&#xff0c;有些数据当方…

PCL 平面点云边界特征提取(alpha shapes)

目录 一、概述 1.1原理 1.2实现步骤 1.3应用场景 二、代码实现 2.1关键函数 2.1.1 点云边界提取 2.1.2 可视化点云与边界 2.2完整代码 三、实现效果 PCL点云算法汇总及实战案例汇总的目录地址链接&#xff1a; PCL点云算法与项目实战案例汇总&#xff08;长期更新&a…

07:(寄存器开发)串口通信

串口通信 1、串口简介2、串口通讯协议3、硬件外设4、发送数据5、使用轮询的方式接收数据&#xff08;USART1&#xff09;6、使用中断的方式接收数据7、串口进行printf重定向 1、串口简介 串口通讯&#xff08;Serial Communication&#xff09;是一种设备间非常常用的串行通讯方…

后端增删改查的基本应用——一个简单的货物管理系统

最终效果&#xff0c;如图所示&#xff1a; 如果想要进行修改操作&#xff0c;可点击某栏修改选项&#xff0c;会在本表格下方弹出修改的具体操作界面&#xff08;点击前隐藏&#xff09;&#xff0c;并且目前的信息可复现在修改框内。 本篇文章通过该项目将后端和前端结合起来…

java内存控制

Java 内存控制是一个相对复杂但至关重要的主题&#xff0c;它涉及到如何高效地管理Java应用程序中的内存资源。在Java中&#xff0c;内存管理主要由Java虚拟机&#xff08;JVM&#xff09;负责&#xff0c;包括内存的分配和回收。尽管如此&#xff0c;作为开发者&#xff0c;我…

2025年5月高项,从0备考信息系统项目管理师 | 备考经验全攻略分享

在逐步摸索备考信息系统项目管理师的过程中&#xff0c;我总结了很多关于班课资料和学习经验&#xff0c;现在与大家分享。&#xff08;全文约3k字&#xff0c;阅读用时约5min&#xff09; 这篇分享帖不仅告诉你关于备考信息系统项目管理师实用的班课资料&#xff0c;还有学习…

Win11 23H2 10月正式版:22631.4317 镜像免费下载!

今日&#xff0c;系统之家小编给您带来2024年10月最新更新的Windows11 23H2正式版系统下载&#xff0c;该版本系统基于微软官方最新Windows11 23H2 22631.4317专业版展开离线制作&#xff0c;没有病毒残留&#xff0c;且能完美支持新老机型&#xff0c;安装后&#xff0c;系统版…

【概率论】泊松分布

泊松分布 若 &#xff0c;则 归一性 例子 泊松分布多出现在当X表示一定时间或一定空间内出现的事件的个数这种场合&#xff0c;如在一定时间内某交通路口所发生的事故的个数。 将泊松分布假设为二项分布 假设条件: &#xff08;1&#xff09;泊松分布一般为一段时间或一…

★ 算法OJ题 ★ 二分查找算法

Ciallo&#xff5e;(∠・ω< )⌒☆ ~ 今天&#xff0c;塞尔达将和大家一起做几道二分查找算法算法题 ~ ❄️❄️❄️❄️❄️❄️❄️❄️❄️❄️❄️❄️❄️❄️ 澄岚主页&#xff1a;椎名澄嵐-CSDN博客 算法专栏&#xff1a;★ 优选算法100天 ★_椎名澄嵐的博客-CSDN博客…

STM32 SPI串行总线

目录 STM32的SPI通信原理 SPI串行总线概述 SPI串行总线互连方式 STM32F1 SPI串行总线的工作原理 SPI串行总线的特征 SPI串行总线的内部结构 SPI串行总线时钟信号的相位和极性 STM32的SPI接口配置 STM32的SPI接口数据发送与接收过程 SPI的HAL 驱动函数 STM32的SPI通信…

靶标弹孔检测系统源码分享

靶标弹孔检测系统源码分享 [一条龙教学YOLOV8标注好的数据集一键训练_70全套改进创新点发刊_Web前端展示] 1.研究背景与意义 项目参考AAAI Association for the Advancement of Artificial Intelligence 项目来源AACV Association for the Advancement of Computer Vision …

apt update报错:ModuleNotFoundError: No module named ‘apt_pkg‘(可能是默认python版本被改坏了)

文章目录 错误信息分析1. 确保 apt_pkg 模块已安装2. 检查 Python 版本3. 重新配置 Python4. 修复损坏的依赖5. 检查环境变量 尝试 错误信息 (base) rootkyai:/ky/tml/ky_ai_get_server_info# apt update 获取:1 file:/var/cuda-repo-cross-aarch64-ubuntu2004-11-4-local InR…

【Python】如何让SQL Server像MySQL一样拥有慢查询日志(Slow Query Log慢日志)

如何让SQL Server像MySQL一样拥有慢查询日志&#xff08;Slow Query Log慢日志&#xff09; SQL Server一直以来被人诟病的一个问题是缺少了像MySQL的慢日志功能&#xff0c;程序员和运维无法知道数据库过去历史的慢查询语句。 因为SQLServer默认是不捕获过去历史的长时间阻塞…

inBuilder低代码平台新特性推荐-第二十五期

今天来给大家带来的是inBuilder低代码平台社区版中的特性推荐系列第二十五期——选人组件扩展&#xff01; 一、概述 inBuilder低代码平台社区版的开发过程中&#xff0c;选人组件支持tab页中增加扩展页面&#xff0c;由二开人员根据业务场景实现自定义取数接口和页面展示形式…

【笔记】济南,天命人,春秋

孤独而高傲的济南人 浩克山东知天命热爱的sensei 浩克山东 哦哦&#xff0c;最高的大葱也是济南的了&#xff0c;这大葱&#xff0c;比一般人要高呢&#xff0c;尽管济南的朋友们也都个子不矮。。能想像的到两米高的米库。。。。 然而在这块地界&#xff0c;遇到个人&#xf…

基于STM32的简易交通灯proteus仿真设计(仿真+程序+设计报告+讲解视频)

基于STM32的简易交通灯proteus仿真设计(仿真程序设计报告讲解视频&#xff09; 仿真图proteus 8.9 程序编译器&#xff1a;keil 5 编程语言&#xff1a;C语言 设计编号&#xff1a;C0091 **1.**主要功能 功能说明&#xff1a; 以STM32单片机和数码管、LED灯设计简易交通…

版本控制系统Helix Core的常见使用误区及解决办法、实用工具及新功能介绍

日前&#xff0c;Perforce携手合作伙伴龙智一同亮相Unreal Fest 2024上海站&#xff0c;分享Helix Core版本控制系统及其协作套件的强大功能与最新动态&#xff0c;助力游戏创意产业加速前行。 Perforce解决方案工程师Kory Luo在活动主会场&#xff0c;带来《Perforce Helix C…

QT安装成功后-在创建项目时,发现仅有项目名文件

&#xff08;1&#xff09;QT安装成功后&#xff0c;发现仅有项目名文件其他可编辑文件缺失 &#xff08;2&#xff09;点击文件名左上角的感叹号显示【No kits are enabled for this project. Enable】 小编在尝试多次后发现&#xff0c;可以通过以下方式解决&#xff1a;QT软…