配列組合せ生成アルゴリズム

10132 ワード


r配列生成:
gen再帰層数dは、d番目の要素が生成されていることを示す.
visレコードが現れたかどうか.
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;


int n, r;
int A[50], vis[50];//   i        
int cnt;
int rer;

void output(int r)
{
    for(int i = 0; i < r; i++) printf("%d ", A[i]);
    printf("
"); } // P(n, r), r==n , // d d void gen(int d) { rer++; if(d == r ) { cnt++; output(r); } else for(int i = 0; i < n; i++) if(!vis[i]) { A[d] = i; vis[i] = 1; gen(d+1); vis[i] = 0; } } void gen1(int d) { for(int i=0;i<n;i++) { if(!vis[i]) { vis[i]=1; A[d]=i; if(d==r-1) output(r); else gen1(d+1); vis[i]=0; } } } int main() { scanf("%d%d", &n, &r); memset(vis, 0, sizeof(vis)); gen(0); gen1(0); //printf("%d
", cnt);
//printf("%d
", rer);
return 0; }

rコンビネーション生成、C(n,r)対応r!個のP(n,r)があるので,要素をインクリメントすることで対応する位置の要素を生成し,C(n,r)を生成することができる.
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;


int n, r;
int A[50], vis[50];//   i        
int cnt;
int rer;

void output(int r)
{
    for(int i = 0; i < r; i++) printf("%d ", A[i]);
    printf("
"); } // C(n, r), // d d void gen(int d, int from) { rer++; if(d == r ) { cnt++; output(r); } else for(int i = from; i < n; i++) if(!vis[i]) { A[d] = i; vis[i] = 1; gen(d+1, i+1); vis[i] = 0; } } void gen1(int d, int from) { for(int i=from;i<n;i++) { if(!vis[i]) { vis[i]=1; A[d]=i; if(d==r-1) output(r); else gen1(d+1, i+1); vis[i]=0; } } } int main() { scanf("%d%d", &n, &r); memset(vis, 0, sizeof(vis)); //gen(0, 0); gen1(0, 0); //printf("%d
", cnt);
//printf("%d
", rer);
return 0; }

参考:プログラム設計における組合せ数学