一组的电源组

Power set of a set

本文关键字:电源 一组      更新时间:2023-10-16

我是算法的新手,在网上发现了这个问题:给定N个数字S1、…的序列。。。,SN(-2000000≤Si≤20000000),确定S的多少个子集(包括空个子集)的和在a和B之间(500000000≤a≤B≤500000000),包括500000000。

For  EXAMPLE:
Sequence : 1 -2 3
A= -2
B=3
The following 5 subsets have a sum between -1 and 2:
0 = 0 (the empty subset)
1 = 1
1 + (-2) = -1
-2 + 3 = 1
1 + (-2) + 3 = 2

我的方法:
取所有可能的组合,即j=2^n,并检查总和代码:

for(int i=0;i<j;i++){
    for(int k=0;k<A.length;k++){
        int temp= 1<<k;
        if( (i&temp) !=0){
            sum+=A[k];
        }
    }
    if(a<=sum &&  sum<=b){
        ans++;
        sum=0;
    }
    cout<<ans<<endl;
}

缺点:如果n>27的值,这个解决方案在我退休之前不会给我答案,我想去看星际电影,它会很棒的
有人能给我一个好的算法或方法来解决这个问题吗

根据我的说法,我应该对数组进行排序,并根据A和B划分数组

好的,扩展我上面的评论。。。。

您可以通过以下方式对此进行分解:-

for a set S and range AB
  for each element in S
    remove element from S, call new set S'
    calculate new range A'B', where A' and B' are altered according to the removed element
    call this function using S' and A'B'

如果S的大小只有一个,那么:-

is element of S within range AB?

我不知道这是否是最有效的解决方案,但这将是我的初步解决方案,无需进一步研究。可能有一种更快的方法,但这对我来说非常NP。

递归在"调用这个函数"一行,谷歌"递归"会提供更多关于该技术的细节。

我们将首先找到具有1个元素的解决方案,然后找到具有2、3、。。。称之为M

首先对集合进行排序。

对于任何M,我们可以按重力向左的顺序递归生成组合,例如:

XX、 。。。

X.X.

.XX…

X。。X.

.X.X.

XX。

等等。

让我假设,对于这个序列的任何成员,我们都知道如何制作下一个或上一个,对于任何M.

现在我认为这个列表是按总值的顺序排列的,所以你知道什么时候在A和B处截断它。对于M=1,你只需要遍历到A,开始输出解决方案,并在超过B时停止,但你也会注意到超过A-S[0]的索引,S[0]是集合中最小的数字。

现在,您以一组由刚刚超过a-S[0]的解决方案组成的解决方案开始运行M=2。这是M=2的最小解决方案。所以继续巡航,直到你超过B.

现在,M=3的起点并不是那么简单。候选者具有较低的tot+x值,其中x是提供的数字,但尚未在集合中。您可以按顺序搜索M=2集合,并在tot-A超过已找到的解决方案的x时停止。

这适用于M.的所有后续值

但我不确定这个序列是否真的是按值的顺序排列的,我也不确定如何编写算法来给出序列中的下一个组合。还是我?这个怎么样:

对于任何组合,要按顺序生成下一个,请找到所有下行边,例如在XX.X中。我们在第二个和第四个X之后有下行边。对于每条边,计算交换X和的结果。选择影响最小的选项。如果它们产生相同的差异,请选择最左边的边缘。现在,如何制作序列中的前一个已经很明显了。