一尘不染

在C中创建n项的k和m组合的所有可能子集

algorithm

我正在寻找解决问题的方法:我必须编写一个代码,计算唯一元素的组合,即将所有选择为k个元素的n个元素的所有不同组合,然后重新计算剩余子集的新组合,而无需复制。给定S(所有可能的唯一元素的集合),我必须计算S的元素的唯一组合的子集T,现在我必须重新计算T的组合的新子集-
V-且所有子集T和V必须为独特:

For example I have this set S: {0, 1, 2, 3, 4}

我必须获得

a {0, 1} {2, 3} { 4} 
b {0, 1} {2, 4} { 3} 
c {0, 1} {3, 4} { 2} 
d {0, 2} {1, 3} { 4} 
e {0, 2} {1, 4} { 3} 
f {0, 2} {3, 4} { 1} 
g {0, 3} {1, 2} { 4} 
h {0, 3} {1, 4} { 2} 
i {0, 3} {2, 4} { 1} 
j {0, 4} {1, 2} { 3} 
k {0, 4} {1, 3} { 2} 
l {0, 4} {2, 3} { 1} 
discarded as the same as g -> {1, 2} {0, 3} { 4} 
discarded as the same as j -> {1, 2} {0, 4} { 3} 
m {1, 2} {3, 4} {0} 
discarded as the same as d -> {1, 3} {0, 2} { 4} 
discarded as the same as k -> {1, 3} {0, 4} { 2} 
n {1, 3} {2, 4}{ 0} 
discarded as the same as e -> {1, 4} {0, 2} { 3} 
discarded as the same as h -> {1, 4} {0, 3} { 2} 
o {1, 4} {2, 3}{0} 
discarded as the same as a -> {2, 3} {0, 1} { 4} 
discarded as the same as l -> {2, 3} {0, 4} { 1} 
discarded as the same as o -> {2, 3} {1, 4} { 0} 
discarded as the same as b -> {2, 4} {0, 1} { 3} 
discarded as the same as i -> {2, 4} {0, 3} { 1} 
discarded as the same as n -> {2, 4} {1, 3} { 0} 
discarded as the same as c -> {3, 4} {0, 1} { 2} 
discarded as the same as f -> {3, 4} {0, 2} { 1} 
discarded as the same as m -> {3, 4} {1, 2} { 0}

{1,2} {0,3} {4}的组合与{0,3} {1,2} {4}的(对此问题)相同,然后必须丢弃,与{1, 2} {0,4} {3}和{0,4}
{1,2} {3}。

是否可以在不使用已考虑组合的数据结构(作为列表)的情况下实现目标?

我需要这样的东西:生成组合:1

它与先前的问题不是重复的,因为研究涉及必须被视为明确的分区,即分区中包含的元素(无论其顺序如何)在先前的细分中必须尚未达成共识,例如,{1,2} {0,4}
{3}和{0,4} {1,2} {3}必须被认为是唯一的,因此只有有效的组合:{0,4} {1,2} {3}


阅读 177

收藏
2020-07-28

共1个答案

一尘不染

比我最初想象的要棘手。

好的,假设您有“ n”个uniq元素。uniq可能性的总和为“ n!”。(因此对于5个元素,您有120个可能性)。

假设您要对“ k”个数字进行“分组”。

因此,如果n = 5且k = 2,您将得到示例:

{0,1},{2,3},{4}。

现在,这就是乐趣的开始:为了知道当前命题是否不是重复命题,您可以舍弃每个未对每个 完整 组中的第一个数字进行排序的命题。

例如 :

{0,1},{2,3},{4}。

在这里,1和3是无用的,因为它不是完整组的第一个值,而4是不完整组的一部分。所以有趣的是

{ 0 ,?},{ 2 ,?},{?}。

是0、2排序吗?是的,因此您可以保留这个主张。这意味着如果你有

{2,3},{0,1},{4}。

不好,因为

{ 2 ,?},{ 0 ,?},{?}。

2,0未排序。


如果n = 6且k = 2,则为

{0,2},{3,4},{1,5}

有效吗?否,因为0 3 1未排序。你可以看到

{0,2},{1,5},{3,4}

是有效的排序命题。


现在,如果我们知道n和k,就有可能计算出多少个有效命题?

是。

也许。我认为…如果可以找到我会更新的。

编辑:

Aaaaaannnd,这里是一个实现。要做一些有趣的事情。它基于以前的算法,因此,如果我的算法为假,则此代码为假。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>



#define N 5
#define K 2


void Comb_Display(int proposition[N])
{
    printf("{");
    for (int i = 0; i < N; ++i) {
        if (i && i % K == 0) {
            printf("} {");
        }
        printf("%d%s", proposition[i], (i && (i + 1) % K == 0) || i + 1 >= N ? "" : ", ");
    }
    printf("}\n");
}

bool Comb_Valid(int proposition[N])
{
    int nbGroup = N / K;

    if (nbGroup == 1) {
        return (true);
    }
    for (int i = 0; i < nbGroup; i += K) {
        if (proposition[i] > proposition[i + K]) {
            return (false);
        }
    }
    return (true);
}

void Comb_MakeMagicPlease(int numberAvailable[N], int proposition[N], int ind)
{
    // We are at the end of the array, so we have a proposition
  if (ind >= N) {
    printf("%s : ", Comb_Valid(proposition) ? "OK" : "  "); // O = Valide, ' ' = invalide
    Comb_Display(proposition);
    return;
  }

  // We scan "numberAvailable" in order to find the first number available
  for (int i = 0; i < N; i++) {
    if (numberAvailable[i] != -1) {
        int number = numberAvailable[i];

        numberAvailable[i] = -1; // We mark the number as not available

      proposition[ind] =  number;
      Comb_MakeMagicPlease(numberAvailable, proposition, ind + 1);
      numberAvailable[i] = number; // we mark the number as available
    }
  }
}

int main(void)
{
  int numberAvailable[N];
  int proposition[N];

  for (int i = 0; i < N; ++i) {
    numberAvailable[i] = i + 1;
  }

  Comb_MakeMagicPlease(numberAvailable, proposition, 0);
  return 0;
}
2020-07-28