且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

查找最小的子集和匹配的另一子集和

更新时间:2022-02-07 21:20:42

这个问题是NP完全问题,因此除非P = NP你坚持做指数工作,对输入的大小。现在的妙处这种类型的问题是,实际上有两种方法可以解决这将给指数对这一问题的不同方面。

This problem is NP-complete, so unless P=NP you are stuck doing exponential work on the size of the input. Now the neat thing about this type of problem is that there are actually two ways to solve which will put the exponent on different aspects of the problem.

首先,如果你的款项没有太多的元素,你可以只是蛮力这个问题通过搜索在所有组合。此方法是指数在套元件的数量,并且将工作相当好高达说每个容器20左右的元件。之后,它是会得到pretty的讨厌。

First if your sums don't have too many elements you can just brute force this problem by searching over all combinations. This method is exponential on the number of elements in the sets, and will work reasonably well up to say 20 or so elements per container. After that it is going to get pretty nasty.

第二个选择是使用动态规划。不像previous方法,该算法是指数的,因为它需要写出来的每一个号码的位数。你要做的就是保持集中的所有可能的款项,以及最小的数字生成它们所需元素的轨道。这是你在​​你的答案链接到溶液的一个简单的修改

A second option is to use dynamic programming. Unlike the previous method, this algorithm is exponential in the number of bits that it takes to write out each of the numbers. What you do is keep track of the set of all possible sums as well as the smallest number of elements required to generate them. This is a simple modification of the solution that you linked to in your answer.

下面是一些Python code产生的所有他们可以相交的可能值:

Here is some python code that generates all the possible values they can intersect at:

    def gen_sum(a):
        r = { 0: [] }
        for x in a:
            for y, v in r.items():
                if not (x+y) in r or len(r[x+y]) > len(v) + 1:
                    r[x+y] = v + [x]
        return r

    def gen_sums(a, b):
        asum = gen_sum(a)
        bsum = gen_sum(b)
        return [ (k, v, bsum[k]) for k,v in asum.items() if k in bsum ][1:]

在你的样本数据运行它,我得到了:

Running it on your sample data, I got:

[(4000,[4000],[2000,2000),(6000,[2000,4000],[565,1435,2000,2000),(2000,[2000],[2000]), (4200,[200,4000],[528,800,2872]),(10200,[200,2000,2000,2000,4000],[528,565,800,1435,2000,2000,2872]), (8200,[200,2000,2000,4000],[528,800,2000,2000,2872]),(6200,[200,2000,4000],[528,800,2000,2872])]

[(4000, [4000], [2000, 2000]), (6000, [2000, 4000], [565, 1435, 2000, 2000]), (2000, [2000], [2000]), (4200, [200, 4000], [528, 800, 2872]), (10200, [200, 2000, 2000, 2000, 4000], [528, 565, 800, 1435, 2000, 2000, 2872]), (8200, [200, 2000, 2000, 4000], [528, 800, 2000, 2000, 2872]), (6200, [200, 2000, 4000], [528, 800, 2000, 2872])]

编辑:修正了一个错字,也只注意到人哇靠吨已经回答了这个非常快

Fixed a typo, and also just noticed that holy crap tons of people have already answered this really quick.