您的位置:首页 > 其它

nyoj_32 组合数

2016-05-02 19:14 225 查看


组合数

时间限制: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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: