nyoj_32 组合数

组合数

时间限制: 3000 ms  |  内存限制: 65535 KB
难度: 3
描述
找出从自然数1、2、... 、n(0<n<10)中任取r(0<r<=n)个数的所有组合。
输入
输入n、r。
输出
按特定顺序输出所有组合。
特定顺序:每一个组合中的值从大到小排列,组合之间按逆字典序排列。
样例输入
5 3
样例输出
543
542
541
532
531
521
432
431
421
321

分析:

假设有一个搜索函数dfs可以解决此问题

那么此问题可以分解为dfs(n,r),dfs(n-1,r),...dfs(r,r)

dfs(n,r)又可以分解为dfs(n-1,r-1),dfs(n-2,r-1),...dfs(r-1,r-1)

此函数一直往深处递归,直到两个参数n和r相等,或者r=1时返回上层。

每往深处递归一层,就能确定一位数,放到队列中。

当n和r相等时,直接能确定r个数,依次放到队列中,然后输出队列中存放的所有数字;

r=1时,也是输出,然后返回。

(我写的连自己也看不懂。。。直接看代码吧)

代码:

#include<cstdio>
#include<deque>
using namespace std;
int vis[15]={0};
deque<int>p,q;/*由于队列的特殊性,输出的时候会清空所有数据,那么前几位数在以后的情况中不会输出。故使用2个队列,一个保存,一个输出。由于在返回以后要去掉刚刚输入到保存队列里的数据,用普通队列无法实现,故使用双端队列。*/
void dfs(int n,int r)
{
	if(n==r)
	{
		for(int i=n;i>=1;i--)
			p.push_back(i);
		q=p;
		for(int i=n;i>1;i--)//留1个在返回后清除
			p.pop_back();
		while(!q.empty())
		{
			printf("%d",q.front());
			q.pop_front();
		}
		printf("\n");
		return;
	}
	p.push_back(n);//每层递归确定一位数
	if(r==1)
	{
		q=p;
		while(!q.empty())
		{
			printf("%d",q.front());
			q.pop_front();
		}
		printf("\n");
		return;
	}
	for(int i=n-1;i>=r-1;i--)
	{
		dfs(i,r-1);
		p.pop_back();
	}
}
int main()
{
	int n,r;
	scanf("%d%d",&n,&r);
	for(int i=n;i>=r;i--)
	{
		dfs(i,r);
		p.pop_back();
	}
	return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值