组合数问题:
描述:
找出从自然数1、2、... 、n(0<n<10)中任取r(0<r<=n)个数的所有组合。
示例:
输入n、r。
输出
按特定顺序输出所有组合。
特定顺序:每一个组合中的值从大到小排列,组合之间按逆字典序排列。
算法分析:
该问题可以从具体的某个数据开始,例先尝试编写n=5r=3时列出所有组合数
从中发现规律,再而进行求解。
我们先从n=5 r=4的问题入手。我们手动按字典序列书写所有组合情况:
1234
1235
1245
1345
2345
观察发现,第一个位置元素有两种情况,即以1开头,以2开头,这是必想到要进行一个循环;再观察第二个位置元素,也是分几种情况,此时又要进行循环,并且是在上一个循环内部进行,同理第三个也是,第四个也是,但此时要输出这四个数字。
代码实现:
#include<stdio.h>
int main()
{
inta[5]={1,2,3,4,5};
inti,j,k,n,h,m;
i=-1;
while(1){//第一个位置下标
i++;
j=i;
while(1){//第二个位置下标
j++;
h=j;
while(1){ //第三个位置下标
h++;
m=h;
while(1){//第四个位置下标
m++;
printf("%d%d %d %d\n",a[i],a[j],a[h],a[m]);
if(m>=4)//循环结束条件,m的值只取3 4
break;
}if(h>=3) //循环结束条件 h的值可取2 3
break;
}
if(j>=2)
break;
}if(i>=1)
break;
}
return0;
}
由此代码观察发现,若r=3 需进行3个嵌套循环,若r=2 需进行2个嵌套循环,此时会出现问题,即若r为一个动态变量,则如何改变嵌套循环个数?大家别忘了递归思想,一个典型的嵌套循环应用稍加思索后我们可以得出以下程序代码求n r的组合
代码实现:
#include<stdio.h>
int b[11]={1,1,1,1,1,1,1,1,1,1,1};
int a[11];
int c[1000];
int N,M,z=1;
int main()
{
intzuhe(int k,int m);
scanf("%d%d",&N,&M);
a[0]=N+1;
zuhe(1,N);
return0;
}
int zuhe(int k,int m)
{
int i,j;
for(i=m;i>=m+M-N;i--){
if(b[i]==1&&(a[k-1]>i)){
a[k]=i;
b[i]=0;
}
else
continue;
if(k==M){
for(j=1;j<=M;j++){
printf("%d",a[j]);
}
printf("\n");
}
elsezuhe(k+1,m-1);
b[i]=1;
}
return0;
}