Algorithm 为使物品重量在1到100之间所需的最小附加重量

Algorithm 为使物品重量在1到100之间所需的最小附加重量,algorithm,recursion,data-structures,dynamic-programming,Algorithm,Recursion,Data Structures,Dynamic Programming,给定一组权重S={w1,w2,w3}和一个权重范围,我们需要确定S中的权重是否可以用于平衡该范围内的每个权重。如果没有,我们需要将最小附加权重添加到S,以便可以平衡范围内的所有权重 例如: 范围为1到5 S={4,8,9} 重量为1的物品可以通过将物品与8放在左盘上,将9放在右盘上来平衡 1+8=9 3+9=8+4 4=4 5+8=9+4 但是2不能用权重{4,8,9}来平衡,所以我们需要添加另一个权重。添加权重1可使2与 2+8=1+9 我的问题是,有没有一种数学算法可以用来解决这个问题?标

给定一组权重
S={w1,w2,w3}
和一个权重范围,我们需要确定
S
中的权重是否可以用于平衡该范围内的每个权重。如果没有,我们需要将最小附加权重添加到
S
,以便可以平衡范围内的所有权重

例如:
范围为1到5
S={4,8,9}

重量为1的物品可以通过将物品与8放在左盘上,将9放在右盘上来平衡

1
+8=9
3
+9=8+4
4
=4
5
+8=9+4

但是2不能用权重{4,8,9}来平衡,所以我们需要添加另一个权重。添加权重1可使2与

2
+8=1+9


我的问题是,有没有一种数学算法可以用来解决这个问题?

标度各边之间的绝对差值是我们的范围。让我们为
s
枚举它们,依次聚合每个元素(将每个元素与之前看到的绝对差相加或相减,然后将元素本身作为差相加):

现在我们来点:

1, 3, 4, 5, 8, 9, 12, 13, 17, 21
为了覆盖1到5的范围,我们需要填补1到3之间的空白。加上1将使我们能产生的每一个差异增加±1

如果要覆盖任何范围,我们是否需要添加
ceil(k/2)
1,其中
k
是我们范围内的最大差距,考虑到我们列举的差异?在这种情况下,ceil(1/2)=1 1

正如ruakh在下面评论的那样,情况并非如此。事实上,我们可以建立的任何较低的范围都可以用来填补任何地方的空白,而填补范围的覆盖范围可以再次应用于不断扩大的范围。例如:

{1, 2} covers 1 to 3

Now add 7 and we've increased our
range to 1 - 10 by virtue of applying ±3 to 7

Now we can add 21 and achieve the
range 21 ± 10!

这就指出了子问题重叠的可能性。

当然有算法可以解决这个问题。为了清楚起见,我假设您使用的术语“集合”是数学集合,其中所有集合元素都是不同的,尽管这不会对下面的代码产生太大影响。 将问题分为两部分:

(1) 确定所提供的一组权重是否可以在秤上排列,以覆盖所需的整数值范围

第(1)部分的python解决方案: (要运行,请调用
check_range(int,int,[])
,其中前两个参数分别是范围的整数边界,低/高,第三个参数是集合中的权重列表)

(2) 如果1。如果为false,则确定完成所需范围所需的最小附加重量

问题的第(2)部分,我还没有添加一个完整的解决方案,但是,我们只需要获取上述代码中的
missing_offset
列表,并将其归结为可以包含在
可能的_offset
集合中的附加权重值,如代码行中执行的:

        for i in l:
            temp.add(i + weight)
            temp.add(abs(i - weight))

这个问题听起来也很像搜索树算法(虽然不是二进制的),也很像组合数学,因此可能有几种有效的方法来计算所需的输出。

请解释这句话“1 | 8-9-for 13 | 9-8 | 4-for 34 | 4-for 45 | 8-9 | 4-for 5”,对于重量为1的项目1来说,所有的事情都搞砸了。平衡可以通过使用重量8和项目本身在左侧,使用重量9在右侧来完成。观察结果:在
S
中的每个砝码都有三个可能的位置:左盘、右盘或未使用。这建议采用3进制编号系统。很容易证明,一组
s={1,3,9,27,…}
可以用来平衡从1到
s
@user3386109的总重量的任何重量,是的,但是这里给出了一组重量,如果可能的话,我们需要使用这些重量来称重range@PrakharT标题实际上与问题不符。标题是否正确,范围始终为1到100?或者范围是算法的输入?如果范围是一个输入,那么问题的约束条件是什么?答案的最后一段不正确;如果我们只能加1,那将是正确的答案,但如果我们可以加任意的权重,那就不一定了。例如,假设S是{1,2,20};然后,它可以用来平衡任何整数1-3或17-20,留下大小为13的间隙。这个答案的最后一段说我们需要在S上加七个1,但事实上我们可以通过只加一个7来完全填补这个空白。@ruakh从技术上讲,这个答案的最后一段既不是对的,也不是错的;这是一个问题:)但谢谢你的精彩观察,这正是我所希望的。这意味着我们的独立范围1-3、17-23(不是20)可以在答案中的任何地方重新应用;因此,当添加7时,我们会立即填补3、7和10之间的空白,使用1到10,20可以填补10-20。但是如何构建一个解决方案呢?假设{1,2,7}覆盖了1到10的范围,那么下一个数字是21,因为
21-10=11
。(
20-10=10
不需要,因为已经覆盖了10。)结果集{1,2,7,21}覆盖了1到31。下一个数字是63,然后是189,等等@user3386109哦,对了;这与您对base 3的评论有关。@•㪞עבקן:好的,很公平。:-)
def get_possible_offsets(s=[]):
    #the variable set "temp" will hold the possible offsets that we can create by arranging the weights on the scale 
    temp=set()

    #optionally, we don't need to add any of the weights, ergo add value 0 by default
    temp.add(0)

    #per every weight in the given set of weights
    for weight in s:

        #take an iterable snapshot of our set of possible offsets
        l = list(temp)

        #for each value in that list, |i+/-w| the weight value
        for i in l:
            temp.add(i + weight)
            temp.add(abs(i - weight))

        #and also add the weight by itself
        temp.add(weight)

    return(temp)

def check_range(r_low=0, r_high=1, s=[]):
    #get the set of weight values available using the provided set of weights
    possible_offsets = get_possible_offsets(s)

    #list to store the required weight values not available using the provided set of weights
    missing_offsets = []

    #for each required weight in the range, check if that weight exists in our current possible offsets
    for i in range(r_low, r_high+1):
        if i not in possible_offsets:
            missing_offsets.append(i)

    #if we're not missing any values from the required range, then we are done!
    if len(missing_offsets) == 0:
        print ("Yes! The required range is covered by the provided weights.")
    else:
        print ("Tragically, the following weight offsets are not covered:",missing_offsets)
        for i in l:
            temp.add(i + weight)
            temp.add(abs(i - weight))