递归

1、递归实现排列型枚举:

从 1~n 这n(n < 20)个整数中随机选取任意多个,输出所有可能的选择方案。

递归求解:这等价于每个整数可以选或者不选,所有可能的总数共有 2^n种。在每次递归中分别尝试某个数选或不选两条分支,将尚未确定的整数数量-1,从而转化为一个规模更小的同类问题。

代码:

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <cmath>
#include <queue>
#include <stack>
#include <set>
#include <map>
#include <vector> 
#define INF 0x3f3f3f3f
#define LL long long
using namespace std;
const int maxn=1005;
int n;
vector<int> chosen;
void calc(int x){
	if(x==n+1){
		for(int i=0;i<chosen.size();i++){
			printf("%d ",chosen[i]);
		}
		printf("\n");
		return ;
	}
	//不选x分支 
	calc(x+1);//求解子问题 
	chosen.push_back(x);//记录x已被选择 
	calc(x+1);//求解子问题 
	chosen.pop_back();//准备回溯到上一问题之前,还原现场 
}
int main(){
	scanf("%d",&n);
	calc(1) ;
    return 0;
}

2、递归实现组合型枚举:

从 1~n 这n(n < 20)个整数中随机选取m个,输出所有可能的选择方案。

我们只需在上面指数型枚举的程序calc函数的开头加上以下这条语句即可。

if(chosen.size() > m || chosen.size() + (n-x+1) < m){
	return ;
}

这就是所谓的“剪枝”。寻找表换路线其实就是搜索的过程,如果能够及时确定当前问题一定是无解的,就不需要到达问题边界才返回结果。

3、递归实现排列型枚举:

把1~n这 n(n < 20) 个整数排成一行后随机打乱顺序,输出所有可能的次序。

该问题也被称为全排列问题,所有可能的方案总数有 n! 种。在每次递归中,我们尝试把每个可用的数作为数列中的下一个数,求解“把剩余的n-1个整数按照任意次序排列”这个规模更小的子问题。

代码:

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <cmath>
#include <queue>
#include <stack>
#include <set>
#include <map>
#define INF 0x3f3f3f3f
#define LL long long
using namespace std;
const int maxn=1005;
int n;
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]);
		}
		printf("\n");
		return ;
	}
	for(int i=1; i <= n; i++){
		if(chosen[i]) continue;
		chosen[i]=true;
		order[k]=i;
		calc(k+1);
		chosen[i]=false;
	}
}
int main(){
	scanf("%d",&n);
	calc(1);
    return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值