在给定数组中生成元素的所有配对的所有集合的有效方法

时间:2018-12-25 10:55:42

标签: c++ backtracking

比方说,我给了数组{1, 2, 3, 4},n(数组的大小)的范围是2到18。我需要找到所有成对排列这些元素的方法。因此,对于此示例,我将得到:

(1, 2), (3, 4)

(1, 3), (2, 4)

(1, 4), (2, 3)

所以顺序在这里很重要,因为我不想/不需要生成配对相同的所有排列(我认为吗?)。 (例如(1, 2), (3, 4)(3, 4), (1, 2)。)

我已经尝试了一种递归回溯的方法,但是对于较大的数组(14-18)来说,这并不是真正有效的时间安排,对于所有可能的输入,我需要不到2s的执行时间。

这是我的代码:

void gen_sol(int k)
{
    if(k > n)
    {
        //do further calculations    
    }
    else
    {
        for(int i = 1; i <= n; i++)
        {
            for(int j = i + 1; j <= n; j++)
            {
                if(k == 1)
                {
                    if(!used[i] && !used[j])
                    {
                        sol[k] = v[i];
                        sol[k + 1] = v[j];
                        used[i] = true;
                        used[j] = true;
                        gen_sol(k + 2);
                        used[i] = false;
                        used[j] = false;
                    }
                }
                else
                {
                    if(sol[k - 2] < v[i] && !used[i] && !used[j])
                    {
                        sol[k] = v[i];
                        sol[k + 1] = v[j];
                        used[i] = true;
                        used[j] = true;
                        gen_sol(k + 2);
                        used[i] = false;
                        used[j] = false;
                    }
                }
            }
        }
    }
}

现在我知道简短的,描述性的名称通常会被皱眉,但是在竞争激烈的编程环境中,我认为这并不算太糟糕。因此k表示递归级别/我正在使用的当前对,sol是我在其中构建当前排列的数组,used用于指示其中的哪些元素我已经使用过的数组。

关于实际的货币对生成,我正在将当前可能的货币对与上一个货币对进行比较,以查看其按字典顺序排序。我知道我可以在循环中合并两个单独的if语句,我应该这样做。

我已经考虑过尝试一种迭代方法,但是使用此方法时n = 18的执行时间太长了,我认为进行迭代不会有太大帮助。

也许有一种方法可以减少一个循环吗?

0 个答案:

没有答案