「DFS」从不同的一组数中选取k个数的总方法

例题:HDOJ1342
在这里插入图片描述

题目大意:

输出从给定的k个数中选取6个数的所有选取方法

题解:

dfs的入门题型是全排列题,其实和这类题很像
全排列题目中dfs函数的写法:

void dfs(int step){
	if(step==Volume+1){
		输出标记数组
	}
	for(int i=0;i<Volume;i++){
		if(vis[a[i]]==0{
			b.push_back(a[i]);
			vis[a[i]]=1;
			dfs(step+1);
			b.pop_back();
			vis[a[i]]=0;
		}
	}
}

我们从这个代码入手,分析选取问题的写法
这个dfs函数中的for循环中每个位置的元素序号都是从0开始的,也就是说很可能出现后面的元素序号比前面的元素的序号小的问题。这样会导致重复的选取出现。
比如:1 2 3 4 和1 2 4 3
要使得选取问题中不出现重复,最好使得后面的元素序号大于前面的,这样是不可能出现重复的情况。
这样我们在代码上加上一个参数NowMax来记录当前选取过的最大序号以使得下一个位置的序号从NowMax+1开始

选取问题的dfs:

void dfs(int step ,int NowMax){
	if(step==Volume+1){
		输出标记数组
	}
	for(int i=NowMax+1;i<Volume;i++){
		if(vis[a[i]]==0{
			b.push_back(a[i]);
			vis[a[i]]=1;
			dfs(step+1,i);
			b.pop_back();
			vis[a[i]]=0;
		}
	}
}

不过这样写记得主函数中要dfs(1,-1),因为最初还没有选取元素
这样,我们就使得每一个输出的序列都是递增的,这样如果不是完全相同的序列,那么就不可能是重复的。

其实这个代码中的vis数组是可以省略的,因为每个for循环都是从前面所有序号中最大的序号后开始遍历的,所以前面也就不可能出现过要遍历的数

选取问题最终版本dfs:

void dfs(int step ,int NowMax){
	if(step==Volume+1){
		输出标记数组
	}
	for(int i=NowMax+1;i<Volume;i++){
			b.push_back(a[i]);
			dfs(step+1,i);
	}
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值