3. Основни комбинаторни алгоритми [1.3] - 21.10.2003

*** Пермутации [1.3.1] наредени n-торки
А. без повторения { 1 2 3 }
123  132  213  231  312  321
Общ брой n!
// permute.c - пермутации без повторения
#include <stdio.h>
#define MAXN 100

const unsigned n = 3;
unsigned char used[MAXN];
unsigned mp[MAXN];

void print(void)
{ unsigned j;
  for (j=0; j<n; j++) printf("%u ", mp[j]+1);
  printf("\n");
}
void permute(unsigned i)
{ unsigned j;
  if (i>=n) { print(); return; }
  for (j=0; j<n; j++)
  { if (!used[j])
    { used[j]=1; mp[i]=j;
      permute(i+1);
      used[j]=0;
    }
  }
}
int main()
{ unsigned j;
  for (j=0; j<n; j++) used[j]=0;
  permute(0);  return 0;
}
Б. с повторения { 1 1 2 3 }
1123  1132  1213  1231  1312  1321  2113  2131  2311  3112  3121  3211
Общ брой n!/(s1!s2!...sk!), където si! е броят на i-тия различен елемент, участващ в мултимножеството. В примера 4!/(2!1!1!) = 12.

*** Вариации [1.3.2] нареден k-елементен списък измежду n елемента (нареден)
А. без повторения n= 3 { 1 2 3 },  k = 2
12  13  21  23  31  32
Общ брой n!/(n - k)!  В примера 3!/1 = 6.
Б. с повторения n= 3 { 1 2 3 },  k = 2
11  12  13  21  22  23  31  32  33
Общ брой nk В примера 32 = 9.
// variate.c - вариации с повторения
#include <stdio.h>
#define MAXN 100

const unsigned n = 3;
const unsigned k = 2;
unsigned mp[MAXN];

void print(void)
{ unsigned j;
  for (j=0; j<k; j++) printf("%u ", mp[j]+1);
  printf("\n");
}
void variate(unsigned i)
{ unsigned j;
  if (i>=k) { print(); return; }
  for (j=0; j<n; j++)
  { mp[i]=j;
    variate(i+1);
  }
}
int main()
{ variate(0); return 0; }

*** Комбинации [1.3.3] k-елементно подмножество измежду n елемента (ненаредено)

А. без повторения n= 5 { 1 2 3 4 5 },  k = 2
12  13  14  15  23  24  25  34  35  45
Общ брой n!/((n - k)!k!)  В примера 5!/(3!2!) = 10.
// comb.c - комбинации без повторения
#include <stdio.h>
#define MAXN 20

const unsigned n = 5;
const unsigned k = 2;
unsigned mp[MAXN];

void print(void)
{ unsigned j;
  for (j=0; j<k; j++) printf("%u ", mp[j]);
  printf("\n");
}
void comb(unsigned i, unsigned after)
{ unsigned j;
  if (i>k) return;
  for (j=after+1; j<=n; j++)
  { mp[i-1]=j;
    if (i==k) print();
    comb(i+1,j);
  }
}
int main()
{ comb(1,0);  return 0; }

Б. с повторения n= 5 { 1 2 3 4 5 },  k = 2
11  12  13  14  15  22  23  24  25  33  34  35  44  45  55
Общ брой (n + k - 1)! / ((n - 1)! k!)  В примера 6!/(4!2!) = 15.