Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/algorithm/10.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/sharepoint/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Algorithm 使用约束拆分子集_Algorithm_Subset Sum - Fatal编程技术网

Algorithm 使用约束拆分子集

Algorithm 使用约束拆分子集,algorithm,subset-sum,Algorithm,Subset Sum,今天,在练习一些算法问题时,我发现了一个有趣的问题。 问题是 您必须将1除以n(缺少一个x)为两个相等的值 使两个半之和相等的半 例如: 如果n=7和x=4 解决方案将是{7,5}和{1,2,3,6} 我可以用蛮力的方法来回答,但我想要一个有效的解决方案 有人能帮我吗?如果元素之和为1→没有x的N是奇数,那么就没有解 否则,您可以在O(N)中找到平衡选择的解决方案 连续四个 首先让我们考虑任何四个连续数的序列可以在两个集合中以相等的和而被划分为: [x,x+1,x+2,x+3]→ [x+3,x]

今天,在练习一些算法问题时,我发现了一个有趣的问题。 问题是

您必须将1除以
n
(缺少一个
x
)为两个相等的值 使两个半之和相等的半

例如:

如果
n=7
x=4

解决方案将是
{7,5}
{1,2,3,6}

我可以用蛮力的方法来回答,但我想要一个有效的解决方案
有人能帮我吗?

如果元素之和为1→没有x的N是奇数,那么就没有解

否则,您可以在O(N)中找到平衡选择的解决方案

连续四个

首先让我们考虑任何四个连续数的序列可以在两个集合中以相等的和而被划分为:

[x,x+1,x+2,x+3]→ [x+3,x];[x+2,x+1]

因此,选择它们并将它们放入集合A B A平衡集合A和集合B

4对面 此外,当我们在一个省略的值上有两对夫妇时,它可以具有类似的属性:

[x-2,x-1,x+1,x+2]→ [x+2,x-2];[x+1,x-1]

所以还是个B

此时,我们可以修复以下情况:

  • 我们有一个四胞胎:我们像案例1一样分割它
  • 我们有两个数字,x和其他两个数字:我们像案例2那样拆分
好的,但它可能发生,我们有3个数字,x和其他3个数字,或者其他条件。我们怎样才能以平衡的方式进行选择呢

+2缺口 如果我们再看一次x上的间隙:

[x-1,x+1]

我们可以注意到,如果我们把两个邻居分成两个独立的集合,我们必须在集合上用更大的和来平衡a+2

平衡尾 我们可以使用序列的最后四个数字:

[4 3 2 1]→ [4, 2] ; [3, 1] → 6.四,

最后,我们必须考虑我们可能没有一个,所以让我们建立另一个例子:

[3 2 1]→ [2] ; [3, 1] → 2.四,

让我们也意识到,我们可以在序列的另一端用ababab(或ababa)模式做同样的事情——如果我们的+2代表B(或A)

4对面+ 令人惊讶的是,如果我们跳过h(奇数!)数字,4仍然保持不变:

[x+3,x+2,x-2,x-3]→ [x+3,x-3];[x+2,x-2]

因此,探索阵列,我们可以一步一步地得出解决方案

例如:

11 10 9 8 7 6 5 4 3 2 1
总和是偶数,因此x只能是偶数:

x = 10
11 - 9 | 8 7 6 5 | 4 3 2 1 → (+2 gap - on A) (4 in a row) (balancing tail)
 A   B   A B B A   B A B A

x = 8
11 10 | 9 - 7 | 6 5 | 4 3 2 1 → (4 across +) (+2 gap - on A) (balancing tail)
 a  b   A   B | b a | B A B A

x = 6
11 10 9 8 | 7 - 5 | 4 3 2 1 → (4 in a row) (+2 gap - on A) (balancing tail)
 A  B B A   A   B   A B B B

x = 4 we have no balancing tail - we have to do that with head
11 10 9 8 | 7 6 | 5 - 3 | 2 1 → (balancing head) (4 across +) (+2 gap)
 A  B A B   A B | b   a | B A

x = 2
11 10 9 8 | 7 6 5 4 | 3 - 1 → (balancing head) (4 in a row) (+2 gap)
 A  B A B   A B B A   B   A
注意到解的对称性是很有趣的。另一个例子

10 9 8 7 6 5 4 3 2 1
总和是奇数,所以x只能是奇数,现在元素的数目是奇数

x = 9
10 - 8 | 7 6 5 4 | 3 2 1 → (+2 gap - on A) (4 in a row) (balancing tail)
 A   B   A B B A   B A B

x = 7
10 9 | 8 - 6 | 5 4 | 3 2 1 → (4 across +) (+2 gap - on A) (balancing tail)
 a b | A   B | b a   B A B

x = 5
10 9 8 7 | 6 - 4 | 3 2 1 → (4 in a row) (+2 gap - on A) (balancing tail)
 A B B A   A   B   B A B

x = 3
10 9 8 7 | 6 5 | 4 - 2 | 1 → (balancing head) (4 across + virtual 0) (+2 gap)
 A B A B   B A | a   b | A

x = 1
10 9 8 7 | 6 5 4 3 | 2 → (balancing head) (4 in a row) (+2 gap virtual 0)
 A B A B   A B B A   B 
最后值得注意的是,只要我们有一个完整的平衡段(即一行4个或四个交叉段),我们就可以从A切换到B

有趣的是,如果您自己尝试,那么请求求和([1…N]-x)的属性甚至会使案例变得非常冗余



我很确定这个算法可以推广——我可能很快就会提供一个修订版。

这个问题可以通过将动态规划的标准与预处理步骤结合起来来解决。这些步骤是O(1)com的步骤

算法(n,x):

  • 总和=n*(n+1)/2
  • neededSum=sum-x
  • If(neededSum%2!=0):返回0

  • 创建数组[1..n]并从中删除x

  • 调用标准子项(arr,0,所需金额/2,[]))
  • 下面给出了subsetsum算法的python实现——打印所有子集

    def subsetsum(arr, i, sum, ss):
        if i >= len(arr):
            if sum == 0:
                print ss
                return 1
            else:
                return 0
    
        ss1 = ss[:]
        count = subsetsum(arr, i + 1, sum, ss1)
        ss1.append(arr[i])
        count += subsetsum(arr, i + 1, sum - arr[i], ss1)
        return count
    
    
    arr = [1, 2, 3, 10, 5, 7]
    sum = 14
    a = []
    print subsetsum(arr, 0, sum, a)
    

    希望有帮助

    您应该检查是否能够达到(和(1到n)-x)/2。数字不包括x。它与子集合总和相同。n=7和x=4的答案也是[7,5],[1,2,3,6]Thanx,我纠正了这个错误。我没有试图证明它,但可能贪婪算法总是有效的(如果有解决方案的话)。你应该花些时间来研究这个方向。你能提供一些参考来更好地研究这个解决方案吗