确定是否有任何双精度组合从设定总和到目标值

2024-03-14

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

例如

dose = 400.0
sizes= [15.0, 30.0, 45.0]

400 不能由这些值的任何总和创建(至少我认为这是真的)。但是,如果变量更改为:

dose = 400.0 
sizes = [10.0, 15.0, 30.0]

我期望结果为 true,因为 10x40 = 400。或者如果这是情况:

dose = 405.0
sizes = [2.5, 15.0, 30.0, 100.0]

我还期望得到一个真实的结果,因为 4x100 + 2X2.5 = 405。

您将如何编写这个算法?这似乎与一个有关子集和 https://en.wikipedia.org/wiki/Subset_sum_problem算法,但就我而言,我希望允许任何设置项的多次出现成为解决方案的一部分。


下列Java实现解决了双值的问题。

Note - Java 以其不准确而闻名 http://www.drdobbs.com/jvm/javas-floating-point-imprecision/240168744处理基于双精度/浮点的算术时。但是,对于较低的精度,此解决方案应该足够了。当然,该算法可以用不太受精度问题影响的编码语言(例如 C++)来实现。 通过容差阈值检查更新了算法。这意味着现在还可以处理更精细的精度。谢谢阿舍普勒 https://stackoverflow.com/users/459640/aschepler指出一个有问题的精度用例。

已经实现了两种算法(基于经典的硬币找零问题 https://www.geeksforgeeks.org/dynamic-programming-set-7-coin-change/) using 一个在线java编译器 https://www.jdoodle.com/online-java-compiler:

  • 它只是返回一个布尔值,指示是否存在提供给定总和的子集
  • 第一个算法的扩展,包含子集中使用的值的列表

代码如下:

import java.util.*;

    public class MyClass {
        public static void main(String args[]) {

        double set[] = {2.5, 15.0, 30.0, 100.0};
        double sum = 405.0;
        int n = set.length;
        if (count(set, n, sum))
            System.out.println("Found a subset with given sum");
        else
            System.out.println("No subset with given sum");
            
        List<Double> listing = new ArrayList<Double>();
        if (countList(set, n, sum,listing))
            System.out.println("Found a subset with given sum: " + listing);
        else
            System.out.println("No subset with  given sum");
    }
    
    public static boolean count( double S[], int m, double n)
    {
        // If n is near 0 then there is 1 solution 
        // (do not include any coin)
        if (n >= -0.00001 && n <= 0.00001)
            return true;
         
        // If n is less than 0 then no 
        // solution exists
        if (n < 0)
            return false;
     
        // If there are no coins and n 
        // is greater than 0, then no
        // solution exist
        if (m <=0 && n > 0)
            return false;
     
        // count is true if one of the solutions (i) including S[m-1] (ii) excluding S[m-1] is true
        return count( S, m - 1, n ) ||
               count( S, m, n-S[m-1] );
    }
    public static boolean countList( double S[], int m, double n, List<Double> listing)
    {
        // If n is near 0 then there is 1 solution 
        // (do not include any coin)
        if (n >= -0.00001 && n <= 0.00001)
            return true;
         
        // If n is less than 0 then no 
        // solution exists
        if (n < 0)
            return false;
     
        // If there are no coins and n 
        // is greater than 0, then no
        // solution exist
        if (m <=0 && n > 0)
            return false;
     
        // count is true if one of the solutions (i) including S[m-1] (ii) excluding S[m-1] is true
        List<Double> with = new ArrayList<>();
        with.add(S[m-1]);
        List<Double> without = new ArrayList<>();
        boolean withResult = countList( S, m, n-S[m-1], with );
        boolean withoutResult = countList( S, m - 1, n, without );
        if(withResult) {
            listing.addAll(with);
        }
        else if (withoutResult) {
            listing.addAll(without);
        }
        return withResult || withoutResult;
    }
}

和输出:

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]

参考:

  • 维基百科中的变革问题定义 https://en.wikipedia.org/wiki/Change-making_problem
  • 硬币找零问题 - 回顾和基于 C++ 的解决方案 https://www.hackerrank.com/challenges/coin-change/problem
  • 硬币交换问题 — 贪婪还是动态规划? https://medium.com/@emailarunkumar/coin-exchange-problem-greedy-or-dynamic-programming-6e5ebe5a30b5
  • Java中的float和double“不准确”结果 http://piotrnowicki.com/2011/02/float-and-double-in-java-inaccurate-result/
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

确定是否有任何双精度组合从设定总和到目标值 的相关文章

  • 如何在不循环的情况下找到小于一个数的最大二的幂? [关闭]

    这个问题不太可能对任何未来的访客有帮助 它只与一个较小的地理区域 一个特定的时间点或一个非常狭窄的情况相关 通常不适用于全世界的互联网受众 为了帮助使这个问题更广泛地适用 访问帮助中心 help reopen questions 如何在不循
  • 使用布隆过滤器有什么好处?

    我正在阅读布隆过滤器 它们看起来很愚蠢 使用布隆过滤器可以完成的任何事情 都可以使用单个哈希函数而不是多个哈希函数在更少的空间内更有效地完成 或者看起来就是这样 为什么要使用布隆过滤器以及它有何用处 亚历克斯已经解释得很好了 对于那些还没有
  • 二和 Leetcode 解释、Hashmap、Javascript

    我只是想知道谁能一步一步解释这个解决方案的算法 我不知道哈希图是如何工作的 您能否还提供一个使用哈希图的基本示例 以便我理解该算法 谢谢你 var twoSum function nums target let hash for let i
  • 旧的 Top Coder 谜语:通过插入 + 来生成数字

    我正在考虑 给定一串数字 找到该字符串等于某个目标数字所需的最少加法次数 每次添加都相当于在数字字符串中的某处插入一个加号 插入所有加号后 照常计算总和 例如 考虑 303 和目标总和为 6 最佳策略是 3 03 我会用蛮力解决它 如下所示
  • 无法对可扩展方法进行多线程处理

    更新 为了帮助澄清我的要求 我发布了一些java代码来表达这个想法 前段时间我问了一个question https stackoverflow com questions 7265576 can brute force algorithms
  • 找到数组中最长的连续体,该连续体中的值的总和等于零模 3

    我编写了一段代码 用于查找数组中最长的连续体 连续体中的值之和等于零模 3 例如对于数组a 2 3 5 7 20 7 我们有 2 3 5 7 20 9 所以输出是 5 我的问题是复杂性 现在是O n 3 一只鸟低声对我说 这可以在O n p
  • 为什么 Fisher Yates 是最有用的洗牌算法?

    您认为现代版本的 Fisher Yates 是最公正的洗牌算法吗 您如何解释数组中每个元素位于其原始位置的概率为 1 n 给定一个完美的伪随机数生成器 梅森扭转者 http en wikipedia org wiki Mersenne Tw
  • 谷歌采访:找到多边形的最大和[关闭]

    这个问题不太可能对任何未来的访客有帮助 它只与一个较小的地理区域 一个特定的时间点或一个非常狭窄的情况相关 通常不适用于全世界的互联网受众 为了帮助使这个问题更广泛地适用 访问帮助中心 help reopen questions 给定一个多
  • 背包多重约束

    我有一个动态规划问题 我花了几个小时研究但没有结果 第一部分很简单 你有一背包物品 你必须最大化这些物品的价值 同时将它们保持在一定的重量以下 问题的第二部分是相同的 只是现在也有一个项目限制 例如 您可以放入袋子中的物品的最大价值是多少
  • 经济模拟的算法?

    我想创建一个游戏 玩家可以创建不同价格的不同产品 称为报价 然后我给他们一定数量的客户 称为需求 现在 我想要一个算法来确定每个参与者的市场份额 当然 我现在就可以使用随机的方式来制作我的 但在这样做之前 我更愿意先问一下 因为我确信在我之
  • 合并排序代码不起作用并显示异常

    public static void Merge int arr int p int q int r int n1 q p int n2 r q int L new int n1 int R new int r n2 for int i 0
  • 使用一个或多个标准 FIFO 队列实现延迟队列 [关闭]

    很难说出这里问的是什么 这个问题是含糊的 模糊的 不完整的 过于宽泛的或修辞性的 无法以目前的形式得到合理的回答 如需帮助澄清此问题以便重新打开 访问帮助中心 help reopen questions 延迟队列是一种队列 其中每条消息都有
  • 如何求能被7整除的数字个数?

    给定一个整数N 如何有效地找到范围内能被 7 整除的数字的个数 其逆序也能被 7 整除 0 10 N 1 Example For N 2 回答 4 0 7 70 77 0到99之间所有能被7整除的数字 它们的倒数也能被7整除 我的方法 简单
  • 是否可以有效地计算 lambda 演算项?

    我最近用 lambda 演算编写了很多程序 我希望能够实时运行其中一些程序 然而 尽管趋势函数范式基于 lambda 演算和 B 约简规则 但我找不到一个不是玩具 不以效率为目的的评估器 函数式语言应该很快 但我所知道的那些语言实际上并不提
  • 3 维装箱算法

    我面临着 3 维装箱问题 目前正在进行一些初步研究 了解哪些算法 启发式方法目前能产生最佳结果 由于问题是 NP 难问题 我不希望在每种情况下都能找到最佳解决方案 但我想知道 1 最好的精确求解器是什么 分支定界 我期望使用合理的计算资源可
  • 在内存无法容纳的大文件中查找“n”个最重复的单词/字符串

    我想验证我的伪代码 建议优化和更好的方法 最重复的单词 按排名 此处的排名定义了您要选择的排名 即前 X 个最重复的单词 外部按字母顺序对所有文件进行排序 下列的这里提到的算法 http www tcs fudan edu cn rudol
  • 集合推导式在 Pydev (Python) 上不起作用

    x for x in range 10 在 IDLE 上完美运行 但是当我在 eclipse 中尝试 使用 Pydev 插件 时 出现语法错误 未定义的变量 x 是因为 Pydev 不支持集合理解什么的吗 我该怎么做才能使这项工作成功 这只
  • 通过 DFS 查找图中的强连通分量

    我正在阅读有关 BFS 和 DFS 的图算法 当我分析通过DFS在图中查找强连通分量的算法时 我想到了一个疑问 为了找到强连通分量 书 Coremen 做了什么 首先它在图上运行 DFS 以获得顶点的完成时间 然后再次以完成时间的降序在图的
  • Java 中的递归回溯解决填字游戏

    我需要在给定初始网格和单词的情况下解决填字游戏 单词可以多次使用或根本不使用 初始网格如下所示 这是一个单词列表示例 pain nice pal id 任务是填充占位符 水平或垂直长度 gt 1 像那样 p pain pal id i c
  • 这个简单的洗牌算法是否会返回一副随机洗牌的扑克牌? [关闭]

    Closed 这个问题是无关 help closed questions 目前不接受答案 您有一个包含 52 张卡片的列表 其中列表中卡片的位置不会移动 您有第二个卡位置列表 首先 位置列表与第一个列表相同 迭代第一个列表 对于第一个列表中

随机推荐