『ACM-算法-枚举法』信息竞赛进阶指南--枚举方法_风骨散人Chiam的博客-程序员秘密

技术标签: 算法  # ACM各类模板  # 贪心+思维+二分+搜索+枚举算法  

你以为枚举是一个一个的找?
还真是


你以为枚举都是for循环?
还真是


但你真的会枚举吗?组合型枚举,指数型枚举,排列型枚举?难道你只会线形枚举?
你可太菜了!

// 递归实现指数型枚举
vector<int> chosen;
void calc(int x) {
    
	if (x == n + 1) {
    
		for (int i = 0; i < chosen.size(); i++)
			printf("%d ", chosen[i]);
		puts("");
		return;
	}
	calc(x + 1);
	chosen.push_back(x);
	calc(x + 1);
	chosen.pop_back();
}

// 递归实现组合型枚举
vector<int> chosen; 
void calc(int x) {
    
	if (chosen.size() > m || chosen.size() + (n - x + 1) < m) return;
	if (x == n + 1) {
    
		for (int i = 0; i < chosen.size(); i++)
			printf("%d ", chosen[i]);
		puts("");
		return;
	}
	calc(x + 1);
	chosen.push_back(x);
	calc(x + 1);
	chosen.pop_back();
}

// 递归实现排列型枚举
int order[20];
bool chosen[20];
void calc(int k) {
    
	if (k == n + 1) {
    
		for (int i = 1; i <= n; i++)
			printf("%d ", order[i]);
		puts("");
		return;
	}
	for (int i = 1; i <= n; i++) {
    
		if (chosen[i]) continue;
		order[k] = i;
		chosen[i] = 1;
		calc(k + 1);
		chosen[i] = 0;
		order[k] = 0;
	}
}


// 模拟机器实现,把组合型枚举改为非递归
vector<int> chosen;
int stack[100010], top = 0, address = 0;

void call(int x, int ret_addr) {
     // 模拟计算机汇编指令call
	int old_top = top;
	stack[++top] = x; // 参数x
	stack[++top] = ret_addr; // 返回地址标号
	stack[++top] = old_top; // 在栈顶记录以前的top值
}

int ret() {
     // 模拟计算机汇编指令ret
	int ret_addr = stack[top - 1];
	top = stack[top]; // 恢复以前的top值
	return ret_addr;
}

int main() {
    
	int n, m;
	cin >> n >> m;
	call(1, 0); // calc(1)
	while (top) {
    
		int x = stack[top - 2]; // 获取参数
		switch (address) {
    
		case 0:
			if (chosen.size() > m || chosen.size() + (n - x + 1) < m) {
    
				address = ret(); // return
				continue;
			}
			if (x == n + 1) {
    
				for (int i = 0; i < chosen.size(); i++)
					printf("%d ", chosen[i]);
				puts("");
				address = ret(); // return
				continue;
			}
			call(x + 1, 1); // 相当于calc(x + 1),返回后会从case 1继续执行
			address = 0;
			continue; // 回到while循环开头,相当于开始新的递归
		case 1:
			chosen.push_back(x);
			call(x + 1, 2); // 相当于calc(x + 1),返回后会从case 2继续执行
			address = 0;
			continue; // 回到while循环开头,相当于开始新的递归
		case 2:
			chosen.pop_back();
			address = ret(); // 相当于原calc函数结尾,执行return
		}
	}
}
版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/weixin_43627118/article/details/105512260

智能推荐

1.4(SQL学习笔记)分组、子查询、联结、组合查询_weixin_34306446的博客-程序员秘密

一、分组  建表及数据填充语句下载:链接:https://pan.baidu.com/s/1WHYafwqKJEKq1kDwCH_Zlg提取码: 3wy4  1.1初识分组  分组是按照某一列,将该列中相同多个相同的数据作为一组,整体分成若干组。  例如有如下表:    例如将vend_id作为依据分组,则会分成三组。  所有vend_id = DLL01为一组,...

JS 正则验证数字或字符(8~16位)_fighting_yu的博客-程序员秘密

这是我们公司校验密码为8~16位数字或字符function isValidatePassword(secretKey128) {var matcher = new RegExp("^(?![0-9]+$)(?![a-zA-Z]+$)[[email protected]#$%^&amp;*_]{8,16}$"); // console.log((matcher.test(secretKey128))...

苹果手机经常开低电量模式,对电池会有影响吗?_苹果开低电量模式伤电池吗_dituicyqz的博客-程序员秘密

苹果手机经常开低电量模式,对电池会有影响吗?需要注意什么问题?苹果手机开启低电量模式,对电池是没有影响的。不过虽然对电池没有影响,但是对您的一些功能的使用会产生影响。比如说:邮箱将不再接收邮件、手机的显示效果将变得差一些,并且后台应用也不再刷新。也就是说,iPhone在低电量模式下面,为了增加手机的续航时间,将一些不是那么重要的应用关掉,进而达到了延长续航的目的。如果从硬件角度的分析,进入低电量模式,意味着手机的处理器芯片进入低功耗模式,芯片的运行频率将变得很低,并且关掉部分模块

为何前端验证之后还需要后端验证。_再写三行的博客-程序员秘密

看一段很简单的代码:    login.htmlHtml代码  span style="font-size: small;">html>      head>          title>Testtitle>          script type="text/javascript" src="jquery-1.3.1.js">script>  

随便推点

至少提升项目交付效率30%的终极套路_广州山猫的博客-程序员秘密

这是山猫的第25篇原创前期的系列文章主要是从相对较细的层面去说明项目该如何实施,本篇就揭秘如何将项目交付效率至少提升30%,这个是“套路之王-招投标软件项目管理”系列文章的核心所在,方法论的本质在于提升项目的整体交付效率。1售前少挖坑不好的项目售前方案可以直接导致项目失败。比如没有从顶层设计层面去做项目方案,曾经我碰到过一个项目就是这种情况,因为没有...

Oracle数据库(传智)学习笔记-02_chinawqf的博客-程序员秘密

子查询: --查询工资比scott高的 员工信息 select sal from emp where ename ='SCOTT' select * from emp where sal >3000 ====把2步合成一步 select * from emp 子查询 where sal > (select sal f

【数据结构】-循环链表(单链表)_数据结构循环单链表_Running Snail的博客-程序员秘密

循环单链表-带头结点1.头文件及类型定义2.循环单链表结点类型定义3.函数声明4.基本操作4.1 初始化循环单链表4.2 判空4.3 判断表尾结点4.4 按位查找4.5 指定结点后插4.6 创建循环单链表4.7 遍历4.10 main函数5.小结1.头文件及类型定义#include&lt;stdio.h&gt;#include&lt;stdlib.h&gt;#define ElemType intusing namespace std;2.循环单链表结点类型定义typedef struct

保证定时任务只在单个服务器执行_mjTree的博客-程序员秘密

写了一个定时任务,半小时执行一次,上线之后发现12个服务器都去执行了。定时任务:读取ftp文件服务器上某个路径下的文件,然后解析文件提取每行特定列的字段,然后把符合条件的话单数据的ID、...

【Java】BitConverter(数字转字节数组工具类)_XKIND的博客-程序员秘密

Java 数字转字节数组工具类/** * 数字转字节数组工具类 */public class BitConverter { /** * 以字节数组的形式返回指定的布尔值 * @param data 一个布尔值 * @return 长度为 1 的字节数组 */ public static byte[] getBytes(boolean...

推荐文章

热门文章

相关标签