使用排列搜索特定组而无需重复和贪婪的方法(作业)

时间:2014-10-28 15:41:33

标签: combinations permutation greedy

我是CS第二年的学生。在我的算法和数据结构课程中,我承担了以下问题:

Input:
2<=r<=20
2<=o<=10
0<=di<=100

Output:
number of combinations
or "NO" if there are none
  • r是整数
  • di是整数
  • o是团体数量

我必须找到正确组合的数量。正确的组合是每个整数都分配给某个组的组合,没有一个组是空的,每个组中的整数之和是相同的:

对于一个例子:

r = 4;
di = {5, 4, 5, 6}
o = 2;

因此每组中的整数总和应该加起来为10:

5 + 4 + 5 + 6 = 20
20 / o = 20 / 2 = 10

所以我们可以制作以下小组:

{5, 5}, {4, 6}
{5, 5}, {6, 4}
{5, 5}, {4, 6}
{5, 5}, {6, 5}

正如我们所看到的,每个组合都与第一个组合基本相同。(组中元素的顺序无关紧要。)

所以实际上我们只有一个正确的组合:{5,5},{4,6}。这意味着输出等于一。

其他例子:

r = 4;
di = {10, 2, 8, 6}
o = 2;

10 + 2 + 8 + 6 = 26;
26 / o = 26 / 2 = 13

无法对这些整数求和,因此输出为&#34; NO&#34;。

我有一个关于完成这件事的想法:

struct Input { // holds data
    int num; // number of integers
    int groups; // number of groups
    int sumPerGroup; // sum of integers per group
    int *integers; // said integers
};

bool f(bool *t, int s) { // generates binary numbers (right to left"
    int i = 0;
    while (t[i]) i++;
    t[i] = 1;
    if (i >= s) return true;
    if (!t[i + 1])
        for (int j = i - 1; j >= 0; j--)
            t[j] = 0;
    return false;
}

void solve(Input *input, int &result) {
    bool bin[input->num];  // holds generated binary numbers
    bool used[input->num]; // integers already used
    for (int i = 0; i < input->num; i++) {
        bin[i] = 0;
        used[i] = 0;
    }

    int solved = 0;
    do {
        int sum = 0;
        for (int i = 0; i < input->num; i++) {  // checking if generated combination gets me nice sum
            if (sum > input->sumPerGroup) break;
            if (bin[i] && !used[i]) sum += input->integers[i]; // if generated combination wasnt used before, start adding up
            if (sum == input->sumPerGroup) { // if its add up as it shoul
                for (int j = 0; j < input->num; j++) used[j] = bin[j]; // mark integers as used
                solved ++; // and mark group as solved
                sum = 0;
            }
            if (udane == input->groups) { // if the number of solved groups is equal to number of groups
                result ++; // it means we found another correct combination
                solved = 0;
            }
        }

    } while (!f(bin, input->num)); // as long as I can get more combinations 
}

所以,主要的想法是: 我生成一些数字组合作为二进制数 我检查一下这个组合是否能给我带来不错的收益 如果是的话,我会注意到它 4.冲洗并重复。

因此,对于来自第一个示例{5,4,5,6}的输入,分为两组:

5 4 5 6
-------
0 0 0 0
1 0 0 0
  ...
1 0 1 0 -> this one is fine, becouse 5 + 5 = 10; I mark it as used
1 1 1 0
  ...
0 1 0 1 -> another one works (4 + 6 = 10); Marked as used
So far i got myself 2 working groups which is equal to 2 groups - job done, it's a correct combination.

我的想法背后的真正问题是,一旦我将其标记为&#34;使用&#34;我就无法使用某个整数。这种方式在更复杂的例子中我会错过很多正确的组。我的问题是,这种问题的正确方法是什么?我已经尝试过递归方法,但它没有做得更好(出于同样的原因)

我的另一个想法是每次在标记某些组时使用输入来排列(例如std:next_permutate(...))整数,但即使在看起来很傻的纸上也是如此。

我不是要求你为我解决这个问题,但是如果你能指出我的推理中存在的任何瑕疵都会很糟糕。

此外,不是母语人士。如果我屠杀任何一句话(我知道我做过),我想提前道歉。

0 个答案:

没有答案