递归与dfs深度优先搜索

递归实现指数型枚举

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>    
using namespace std;

int sta[16];   //开状态数组,全局数组,每个函数都能改,dfs函数调用时不用传入
				//全局变量,初始值就是0,sta[0]==0
//0--还没考虑,1--选,2--不选
int n;   //定义到全局变量,不用传入函数

void dfs(int u)    //u是当前位置,
{
	if (u>n)     //输出过程,u是从1开始,所以结束标志就是u>n
	{
		for (int i = 1; i <= n; i++)
			if (sta[i] == 1)
				printf("%d ", i);
		puts("");//打印换行
		return;
	}
    
	sta[u] = 2;//遍历,不选分支,
	dfs(u + 1);//递归第一个分支
	sta[u] = 0;//恢复现场,

	sta[u] = 1;//遍历,选分支,
	dfs(u + 1);//递归第二个分支,选分支,
	sta[u] = 0;


}


int main()
{
	cin >> n;
	dfs(1);    //从第一位开始(为了方便,数范围就是1~15,和给的数字范围匹配)
}

递归实现排列型枚举

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>    
using namespace std;
//顺序:依次枚举每个个位置放哪个数,
//递归树
int n;

int sta[10]; //0表示没放数,1~n表示放了哪个数
int used[10];  //全局变量都为0
void dfs(int u)
{
	//step1,输出最后一层,每个坑里的萝卜输出出来
	if (u > n) //边界
	{
		for (int i = 1; i <= n; i++)
			cout << sta[i] << " ";  //打印方案
		puts("");
		
	}
	//step2,依次枚举每个分支,即当前位置可以填哪些数,
	for (int i = 1; i <= n; i++)
	{
		if (!used[i])
		{
			sta[u] = i;
			used[i] = 1;
			dfs(u + 1);

			//恢复现场,有借有还
			sta[u] = 0;
			used[i] = 0;
		}
	}
}
int main()
{

	cin >> n;
	dfs(1);  //输入的是位置


}

递归实现组合型枚举

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
int n, m;
//sta[]数组装萝卜,层数u,
//组合,升序组合,不重复,就要设star,就是从哪里开始选
//如i==1选了,那下一位就从star==i+1==2开始
//与全排列不同,不用判是否为空use[]
const int N = 40;
int sta[N];

void dfs(int u, int star)
{
    //step1,拔萝卜
	if (u > m)
	{
		for (int i = 1; i <= m; i++)
			printf("%d ", sta[i]);
		puts("");
		return;
	}
	//step2,递归,dfs
	for (int i = star; i <= n; i++)
	{
		sta[u] = i;
		dfs(u + 1, i + 1);
		sta[u] = 0;  //恢复现场 ,回溯
	}

}

int main()
{
	
	cin >> n >> m;
	dfs(1, 1);//深度优先搜索,u==1,star==1
}

                                                                                                  不知细叶谁裁出,二月春风似剪刀

                                                                                                                  2022年2月6日23:44:15   

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值