Algorithm 确定是否有从设定和到目标值的任何双倍组合

Algorithm 确定是否有从设定和到目标值的任何双倍组合,algorithm,set,Algorithm,Set,我在工作中遇到了一个让我有点困惑的问题。我需要验证给定剂量的药物是否可以由药丸剂量大小的任意组合构成 比如说 dose = 400.0 sizes= [15.0, 30.0, 45.0] 400不能由这些值的任何和来创建(至少我认为这是真的)。但是,如果变量更改为: dose = 400.0 sizes = [10.0, 15.0, 30.0] 我希望结果为真,因为10x40=400。或者如果这是塞纳里奥: dose = 405.0 sizes = [2.5, 15.0, 30.0, 10

我在工作中遇到了一个让我有点困惑的问题。我需要验证给定剂量的药物是否可以由药丸剂量大小的任意组合构成

比如说

dose = 400.0
sizes= [15.0, 30.0, 45.0]
400不能由这些值的任何和来创建(至少我认为这是真的)。但是,如果变量更改为:

dose = 400.0 
sizes = [10.0, 15.0, 30.0]
我希望结果为真,因为10x40=400。或者如果这是塞纳里奥:

dose = 405.0
sizes = [2.5, 15.0, 30.0, 100.0]
我还希望得到一个真实的结果,因为4x100+2X2.5=405


您如何编写此算法?它似乎与算法有关,但在我的例子中,我希望允许任何集合项的多次出现成为解决方案的一部分

一种标准方法是:

  • 将你所有的双打都表示为有理数,因此
    [2.5,15.0,30.0,100.0]
    变成
    [5/2,15,30,100]
  • 乘以分母的LCM得到整数大小:
    [5,30,60,200]
    剂量为
    810
  • 检查您所需的剂量是否是GCF大小的倍数:是,
    810
    5
    的倍数(如果不是,则显然无法进行)
  • 除以尺寸的GCF:
    [1,6,12,40]
    和剂量
    162
  • 将标准动态规划解决方案应用于“”。网上有很多关于这方面的资源,例如

  • 下面的
    Java
    实现解决了双值问题

    注意-处理基于双精度/浮点运算的算法时。但是,对于较低的精度,此解决方案应足够。自然地,该算法可以用编码语言实现,而不受诸如C++之类的精度问题的影响。 使用容差阈值检查更新了算法。这意味着现在还可以处理更高的精度。感谢您指出了一个有问题的精度用例

    使用以下方法实现了两种算法(基于经典算法):

    • 一种简单地返回一个布尔值,指示是否有提供给定和的子集
    • 第一个算法的扩展,包含子集中使用的值列表
    代码如下:

    import java.util.*;
    公共类MyClass{
    公共静态void main(字符串参数[]){
    双集[]={2.5,15.0,30.0,100.0};
    双和=405.0;
    int n=设置长度;
    if(计数(集合、n、和))
    System.out.println(“找到具有给定和的子集”);
    其他的
    System.out.println(“没有给定和的子集”);
    List List=new ArrayList();
    if(计数列表(集合、n、总和、列表))
    System.out.println(“找到一个具有给定和的子集:“+列表”);
    其他的
    System.out.println(“没有给定和的子集”);
    }
    公共静态布尔计数(双S[],整数m,双n)
    {
    //如果n接近0,则有1个解
    //(不包括任何硬币)
    
    如果(n>=-0.00001&&n=-0.00001&&n您的标题是“双打”,但所有的例子都是整数。可能有一些算法对整数输入很有效,但对浮点输入根本不起作用。@切普勒:好的,我更新了我的问题。你能通过乘以适当的因子将双精度转换成整数吗?如果是,那么动态规划可以解决整数问题Chick McNugget若你们有两种尺寸,那个么这个定理就解决了常数时间内整数的这个问题:若你们的规格实际上是“double”@柯波斯坦克斯:抱歉,比较迟的评论答案。两个算法确实返回了他们发现的第一个集合。你可以重新排序一组输入的大小,以便得到其他可能的解决方案。算法使用从上到下的大小。C++也可以有浮点不准确,这是在所有语言中都可以使用浮点数的固定大小表示形式。@pkpnd:True,这是使用位系统来描述十进制数的固有问题。根据我以前的经验,C/C++只需比Java更好地处理这些错误。@pkpnd:Fair够了。感谢您的输入。这提醒了我s me-你的答案是一个很好的简化示例(在本例中,特别是从双输入问题到整数输入问题)。向上投票你的答案。@RannLifshitz你将如何使用list方法返回所有可能的和到目标的组合?
    Found a subset with given sum
    Found a subset with given sum: [100.0, 100.0, 100.0, 100.0, 2.5, 2.5]
    
    double set[] = {2.5, 15.0, 30.0, 100.0, 0.2, 0.3};
    double sum = 165.9;
    Found a subset with given sum
    Found a subset with given sum: [0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 100.0, 2.5, 2.5, 2.5, 2.5, 2.5]
    
    double set[] = {0.2, 0.3, 2.5, 15.0, 30.0, 100.0};
    double sum = 148.6;
    Found a subset with given sum
    Found a subset with given sum: [100.0, 30.0, 15.0, 2.5, 0.3, 0.3, 0.3, 0.2]
    
    double set[] = {0.05, 0.012, 0.008};
    double sum = 0.1;
    Found a subset with given sum
    Found a subset with given sum: [0.008, 0.008, 0.008, 0.008, 0.008, 0.008, 0.008, 0.008, 0.008, 0.008, 0.008, 0.012]