#include <iostream>
using namespace std;
const int MAX=10;
int a[MAX];
void com(int n ,int m,int s) //s表示当前被选元素的下标
{
if(s==m+1)
{
for(int i=1;i<=m;i++)
cout<<a[i]<<" ";
cout<<endl;
return;
}
for(int i=a[s-1]+1;i<n-(m-s)+1;i++)
{
a[s]=i;
com(n,m,s+1);
}
}
int main()
{
a[0]=0;
com(5,3,1);
return 0;
}
//非递归算法
void comb_back(int m,int r)
{
int *a = new int[r];//创建一个新数组存储构成组合的3个数
int i,j,k=0;
i=0,a[i]=1;
do{
//a[i]-i<+m-r+1 是判断a[i]的值是否在范围之内如i=0时,a[i]最大可以为倒数第r个数,这样本组数的最大值才不至于大过m
if(a[i]<=m-r+1+i)
{
if(i==r-1) //到了最底层,就一直运行这一分支
{
cout<<"第"<<++k<<"组: ";
for(j=0;j<r;j++)
cout<<a[j];//打印每个组合中的数字
cout<<endl;
a[i]++;
continue;
}
i++; //前进到下一层试探,深搜
a[i]=a[i-1]+1;
}else{ //回溯到上一层进行试探
if(i==0)
return; //已经找到了所有层的解
a[--i]++; //前一层的数字增加1,继续进行向前试探,其总共就r层
}
}while(1);
delete []a;
}
int main()
{
comb_back(5,3);
}
ps..
因为a[i]-i<=m-r+1
所以 a[i]<=m-r+i+1
也就是说m-r+i+1是a[i]上限呀!至于下限就不要考虑了!为什么呢?因为这种组合有一个规律就是后一个数至少比前一个数大1(如下),向前试探是在前一个数的基础上的:a[i]=a[i-1]+1
比如:comb_back(5,3)
a[0]的范围是1 (a[0]=1) 到3 (m-r+i+1=5-3+0+1=3)
a[1]的范围是2 (a[1]=a[0]+1) 到4 (m-r+i+1=5-3+1+1=4)
a[2]的范围是3 (a[2]=a[1]+1) 到5 (m-r+i+1=5-3+2+1=5)
a[0] a[1] a[2]
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
方法二:
#include <stdio.h>
#define N 100
int a[N];
int last;
void zuhe(int m,int k)//从m个元素中取出k个元素的组合
{
int i,j;
for(i=m; i>=k; i--)
{
a[k]=i;//最后一个位置的元素可以取m,m-1,m-2.....k
if(k>1) zuhe(i-1,k-1);//递归调用
else
{
for(j=1;j<=last;j++)
printf("%d ",a[j]);
printf("\n");
}
}
}
void main()
{
int n,m;
printf("请输入Cn,m中n与m的值:");
scanf("%d%d",&n,&m);
if(n>100)
printf("数字太大了!");
last=m;
zuhe(n,m);
}