戻る

組み合わせ列挙プログラム

組み合わせを列挙するプログラムを考えます。
いきなりは難しそうなので、単純に5C3を、123, 124, 125, 134, 135, 145, 234, 235, 245, 345のように表示させるプログラムを考えてみます。
#include <stdio.h>
int main(void)
{
   int i,j,k;
   for(i=1;i<=3;i++){
      for(j=i+1;j<=4;j++){
         for(k=j+1;k<=5;k++){
            printf("%d%d%d\n", i,j,k);
         }
      }
   }
}


8C3だとどうなるでしょう?
#include <stdio.h>
int main(void)
{
   int i,j,k;
   for(i=1;i<=6;i++){
      for(j=i+1;j<=7;j++){
         for(k=j+1;k<=8;k++){
            printf("%d%d%d\n", i,j,k);
         }
      }
   }
}


さて、昔の組合せの教科書をみると、nCr=n-1Cr+n-1Cr-1という公式が出てきます。
関数で表すと、f(n,r)=f(n-1,r)+f(n-1,r-1)ということです。
もしかしたら再帰関数が使える???

つまり、
f(8,3)=f(7,3)+f(7,2)
        ={f(6,3)+f(6,2)}+{f(6,2)+f(6,1)}

ということで、次のようなcombi(n,r)関数を定義してプログラムしてみました。
#include <stdio.h>
int combi(int n, int r)

int main(void)
{
   int combi(8,3);
}

int combi(int n, int r)
{
   if(r>0){
      combi(n-1, r)


  #include <stdio.h>

int num = 0;
void combi(int A[], int p, int w, int n, int r);

int main(void)
{
 int n = 5;
 int r = 3;
 int K[128];
 combi(K, r, n-r, n, r);
 return 0;
}

void combi(int A[], int p, int w, int n, int r)
{
 if(p > 0)               /*  ☆  */
 {
  int i;
  for(i = 0;i <= w;i++)
  {
   A[p] = i;
   
combi(A, p - 1, w - i, n, r);
  }
 } else {                                              /*  ★   */
  int i, j, m;
  num++;
  printf("%d:\t", num);
  m = 0;
  for(i = 1;i <= r;i++){
   for(j = 0;j < A[i];j++, m++)
   printf("0");
   printf("1");
   m++;
  }
  for(;m < n;m++)
  printf("0");
  printf("\n");
 }
}
赤い文字の部分からわかるように、このプログラムは再帰プログラムです。

変数numを宣言。numの初期値を0とする。

関数combiを定義。引数はA, p, w, n, r。











☆再帰からの脱出条件。p=0になると★に進む。