#include <iostream>
using namespace std;
/**///
// 功能 : 从0....m中选取n个的所有组合
// idx[]: 用来记录一个组合, 如: 0,1,3表示选取的是第1,2,4个元素的组合
// start: 起始下标
// cnt : 剩下还要组合元素的个数
// 备注:
// 此算法的思想是: 要从0...m中选取n个元素的组合, 可以问题分解为:把0选进来, 然后再在1...m中选取
// n-1个元素, 和没有把0选进来, 在1...m中选取n个元素.
// 然后: 用同样的办法,分解从1...m中选取的n-1个元素的组合.
// 例如: 从0 1 2 3 中选取3个算法
// 首先: start从0, cnt = 3, com(idx,0, 3, 4, 3); 首先把0选中, 剩下的从1 2 3 中选取2个的组合.即为com(idx,1,2,4,3)
// 若不把0选上,即从1 2 3 中选3个即:com(idx, 1, 3, 4, 3);
// 从m个元素中选取n个的的组合, 这里只是生成下标组合,即不是具体元素的组合.
/**///
void com(int idx[], int start, int cnt, const int &m, const int & n)
... {
if(start + cnt > m) return ;
if(cnt == 0) //cnt为0 表示选取了n个元素了,即找到了一个组合.
...{
for(int i = 0; i < n; i++)
cout<<idx[i]<<" ";
cout<<endl;
return;
}
//把start选中
idx[n - cnt] = start;
com(idx,start + 1, cnt - 1, m, n);
if(start + cnt < m)
com(idx, start + 1, cnt, m, n);
}
/**///
// idx[] : 用来记录组合下标
// m : 要组合元素的总个数
// n : 要选取的元素个数.
// 如: p(6, 5) 表示从6个元素中选取5个 则: m=6, n=5
/**///
void combine(int idx[], const int &m, const int & n)
... {
if(n <= m && n > 0)
com(idx, 0, n, m, n);
}
int main()
... {
int index[20],m,n;
while(cin>>m>>n)
...{
combine(index, m, n);
}
return 0;
}
/**//************************************************************************/
/**/ /* 测试用例:
6 4
0 1 2 3
0 1 2 4
0 1 2 5
0 1 3 4
0 1 3 5
0 1 4 5
0 2 3 4
0 2 3 5
0 2 4 5
0 3 4 5
1 2 3 4
1 2 3 5
1 2 4 5
1 3 4 5
2 3 4 5 */
/**//************************************************************************/
如果是想要输出具体元素的值,如从数组char a[4] = a b c d 中选3个的组合, 因为上面是考虑下标组合, 只要在输出是把idx[i]设为 a[idx[i]] 即可. 不过这里组合没有考虑元素中有重复的情况.