子集生成的两种方法

2024-08-27 06:32
文章标签 方法 生成 子集 两种

本文主要是介绍子集生成的两种方法,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

该算法来自--刘汝佳的算法竞赛入门经典。书中介绍了两种算法的核心代码,但却没有逐过程详细解说,另初学者看文字时很难看懂,

遇到问题,是先要直接研究问题的细节呢还是先把问题搞清楚?我认为绝对应该先学习如何去解决问题,构造方法的框架,而不是先去研究细节。

//方法一:
//思路:一次选出一个元素放到集合中
[cpp] view plain copy
  1. #include <iostream>  
  2. using namespace std;  
  3. int a[20];  
  4. /*递归输出n以内所有的子集,其中cur为当前下标,初始值0*/  
  5. void print_subset(int n,int* a,int cur){  
  6.     for (int i=0;i<cur;i++)//每次递归输出当前子集,靠它来最后输出上一层指定的子集  
  7.         cout<<a[i]<<' ';  
  8.     cout<<endl;//以行分隔  
  9.     //找到当前子集首个值,因为按字典顺序输出,所以每次找到最小的元素,cur>0则minElem=a[cur-1]+1,否则为0  
  10.     int minElem = cur?a[cur-1]+1:0;  
  11.   
  12.     //从子集第一个值开始遍历,先不看下面的print_subset(n,a,cur+1);但看这for循环,  
  13.     //可知是将子集第一个值从头往后依次赋值为minElem-n-1.每次第一个值变化后递归设置下一个值(相当于下一层的第一个值)  
  14.     for (int i=minElem;i<n;i++){  
  15.         a[cur]=i;//当前层子集第一个值  
  16.         //cur+1表示当前层值设置完毕,开始递归下一层,和前面步骤一样。  
  17.         //到达最后一层结束后return 到上一层,然后i++,a[cur]的值(首元素)改变,又反复递归下一层...  
  18.         print_subset(n,a,cur+1);  
  19.     }  
  20. }  
  21.   
  22. int main(){  
  23.     int n ;  
  24.     while (cin>>n,n){  
  25.         print_subset(n,a,0);  
  26.     }  
  27. }  



//方法二:
//思路:构造一个位向量b[],而不是直接构造子集A本身

[cpp] view plain copy
  1. #include <iostream>  
  2. using namespace std;  
  3. bool b[20]={0};//判断当前每一个节点选中状态  
  4. /*递归输出n以内所有的子集,其中b表示该节点是否选中,cur为当前下标,初始值0*/  
  5. void print_subset(int n,bool* b,int cur){  
  6.     //当cur加到n的时候输出该串节点(解答树)的值  
  7.     if(cur==n){  
  8.         for (int i=0;i<n;i++){  
  9.             if(b[i])  
  10.                 cout<<i<<' ';  
  11.         }  
  12.         cout<<endl;  
  13.         return ;  
  14.     }  
  15.     b[cur]=true;//该节点设为选中状态  
  16.     print_subset(n,b,cur+1);//cur+1递归该状态时的下一层节点,循环该操作  
  17.     b[cur]=false;//该节点设为不选中状态  
  18.     print_subset(n,b,cur+1);//cur+1递归该状态时的下一层节点,循环该操作  
  19. }  
  20.   
  21. int main(){  
  22.     int n ;  
  23.     while (cin>>n,n){  
  24.         print_subset(n,b,0);  
  25.     }  

这篇关于子集生成的两种方法的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!


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

相关文章

CentOS7增加Swap空间的两种方法

《CentOS7增加Swap空间的两种方法》当服务器物理内存不足时,增加Swap空间可以作为虚拟内存使用,帮助系统处理内存压力,本文给大家介绍了CentOS7增加Swap空间的两种方法:创建新的Swa... 目录在Centos 7上增加Swap空间的方法方法一:创建新的Swap文件(推荐)方法二:调整Sww

QT6中绘制UI的两种方法详解与示例代码

《QT6中绘制UI的两种方法详解与示例代码》Qt6提供了两种主要的UI绘制技术:​​QML(QtMeta-ObjectLanguage)​​和​​C++Widgets​​,这两种技术各有优势,适用于不... 目录一、QML 技术详解1.1 QML 简介1.2 QML 的核心概念1.3 QML 示例:简单按钮

使用Python自动化生成PPT并结合LLM生成内容的代码解析

《使用Python自动化生成PPT并结合LLM生成内容的代码解析》PowerPoint是常用的文档工具,但手动设计和排版耗时耗力,本文将展示如何通过Python自动化提取PPT样式并生成新PPT,同时... 目录核心代码解析1. 提取 PPT 样式到 jsON关键步骤:代码片段:2. 应用 JSON 样式到

SpringBoot实现二维码生成的详细步骤与完整代码

《SpringBoot实现二维码生成的详细步骤与完整代码》如今,二维码的应用场景非常广泛,从支付到信息分享,二维码都扮演着重要角色,SpringBoot是一个非常流行的Java基于Spring框架的微... 目录一、环境搭建二、创建 Spring Boot 项目三、引入二维码生成依赖四、编写二维码生成代码五

Oracle 通过 ROWID 批量更新表的方法

《Oracle通过ROWID批量更新表的方法》在Oracle数据库中,使用ROWID进行批量更新是一种高效的更新方法,因为它直接定位到物理行位置,避免了通过索引查找的开销,下面给大家介绍Orac... 目录oracle 通过 ROWID 批量更新表ROWID 基本概念性能优化建议性能UoTrFPH优化建议注

Pandas进行周期与时间戳转换的方法

《Pandas进行周期与时间戳转换的方法》本教程将深入讲解如何在pandas中使用to_period()和to_timestamp()方法,完成时间戳与周期之间的转换,并结合实际应用场景展示这些方法的... 目录to_period() 时间戳转周期基本操作应用示例to_timestamp() 周期转时间戳基

在 PyQt 加载 UI 三种常见方法

《在PyQt加载UI三种常见方法》在PyQt中,加载UI文件通常指的是使用QtDesigner设计的.ui文件,并将其转换为Python代码,以便在PyQt应用程序中使用,这篇文章给大家介绍在... 目录方法一:使用 uic 模块动态加载 (不推荐用于大型项目)方法二:将 UI 文件编译为 python 模

Python将字库文件打包成可执行文件的常见方法

《Python将字库文件打包成可执行文件的常见方法》在Python打包时,如果你想将字库文件一起打包成一个可执行文件,有几种常见的方法,具体取决于你使用的打包工具,下面就跟随小编一起了解下具体的实现方... 目录使用 PyInstaller基本方法 - 使用 --add-data 参数使用 spec 文件(

Python的pip在命令行无法使用问题的解决方法

《Python的pip在命令行无法使用问题的解决方法》PIP是通用的Python包管理工具,提供了对Python包的查找、下载、安装、卸载、更新等功能,安装诸如Pygame、Pymysql等Pyt... 目录前言一. pip是什么?二. 为什么无法使用?1. 当我们在命令行输入指令并回车时,一般主要是出现以

通过C#获取Excel单元格的数据类型的方法详解

《通过C#获取Excel单元格的数据类型的方法详解》在处理Excel文件时,了解单元格的数据类型有助于我们正确地解析和处理数据,本文将详细介绍如何使用FreeSpire.XLS来获取Excel单元格的... 目录引言环境配置6种常见数据类型C# 读取单元格数据类型引言在处理 Excel 文件时,了解单元格