1 题目
问题 B: 【递归入门】组合的输出
时间限制: 1 Sec 内存限制: 128 MB
提交: 1062 解决: 655
[提交][状态][讨论版][命题人:外部导入]
题目描述
排列与组合是常用的数学方法,其中组合就是从n个元素中抽出r个元素(不分顺序且r < = n),我们可以简单地将n个元素理解为自然数1,2,…,n,从中任取r个数。
现要求你不用递归的方法输出所有组合。
例如n = 5 ,r = 3 ,所有组合为:
1 2 3
1 2 4
1 2 5
1 3 4
1 3 5
1 4 5
2 3 4
2 3 5
2 4 5
3 4 5
输入
一行两个自然数n、r ( 1 < n < 21,1 < = r < = n )。
输出
所有的组合,每一个组合占一行且其中的元素按由小到大的顺序排列,所有的组合也按字典顺序。
2 参考代码
- 递归版本
#include <cstdio>
const int MAXN = 100;
bool hashTable[MAXN] = {false};
int A[MAXN];
int N, R;
void BFS(int index, int r){//r:累计的个数
if(r == R + 1) {
for (int i = 1; i != R + 1; ++i)
{
printf("%d ", A[i]);
if(i <= R) printf(" ");
}
printf("\n");
return;
}
for (int i = index; i <= N; ++i)//将index~N填入P[r]中
{
if(hashTable[i] == false){
A[r] = i;//令A的第r位等于i
hashTable[i] = true;
BFS(i, r + 1);
hashTable[i] = false;
}
}
}
int main(){
scanf("%d%d", &N, &R);
BFS(1, 1);
return 0;
}
- 栈版本
#include <cstdio>
#include <stack>
#include <vector>
using std::stack;
using std::vector;
vector<int> vec;
stack<int> S;
int N, R;
void BFS(int index){
S.push(index);//存储是否已在vec中
vec.push_back(index);//输出向量
int x;
bool popFlag = false;//是否弹出一个元素
while(!S.empty()){
if(vec.size() == R){
for (vector<int>::const_iterator it = vec.begin(); it != vec.end(); ++it)
{
if(it != vec.begin()){
printf(" ");
}
printf("%d", *it);
}
printf("\n");
popFlag = true;
}
x = S.top();
if(x == N){//该位置1~N元素都测试过一遍,栈中一次弹出两个元素,
// 如1、2、5弹出2、5,栈顶指针指向2
// 如1、4、5弹出4、5,栈顶指针指向4
S.pop();
vec.pop_back();
popFlag = true;
continue;
}
if(popFlag == true){
S.pop();
vec.pop_back();
popFlag = false;
}
if(x < N){
S.push(x + 1);
vec.push_back(x + 1);
}
}
}
int main(){
scanf("%d%d", &N, &R);
BFS(1);
return 0;
}