【问题标题】:Divide optimally an array into two subarrays so that sum of elements in both are same将一个数组最优地划分为两个子数组,使两个子数组中的元素之和相同
【发布时间】:2016-08-02 22:04:21
【问题描述】:

我得到了这样的等式:

    n = 7
    1 + 1 - 4 - 4 - 4 - 2 - 2

如何以最佳方式替换运算符,使等式之和为零,或打印 -1。 我想到了一种算法,但它不是最优的。我有一个想法来暴力破解所有复杂的情况O(n*2^n),但(n < 300)

这里是问题的链接:http://codeforces.com/gym/100989/problem/M

【问题讨论】:

    标签: algorithm dynamic-programming brute-force


    【解决方案1】:

    您正在尝试解决Partition Problem;即将整数分成两个子集,它们的总和相同,并为一个子集中的整数分配正号,为另一个子集中的整数分配负号。

    在您的特定问题中,您对整数的数量和这些整数的值都有一个下限。您可以使用包含/排除方法的标准动态算法方法;即通过考虑不使用最后一个整数的情况,找到总和为i的第一个n整数的子集(因此您需要第一个n-1整数的子集总和为i)以及它的使用位置(第一个 n-1 整数的子集总和为 i - val(n))。

    【讨论】:

    • 虽然此链接可能会回答问题,但最好在此处包含答案的基本部分并提供链接以供参考。如果链接页面发生更改,仅链接答案可能会失效。 - From Review
    • @manetsus - 答案的文本给出了要点,即 OP 试图回答的问题的名称。在这种情况下,链接不是回答问题所必需的;这只是锦上添花。
    【解决方案2】:

    这是一个想法:

    1. 对第 2 到第 N 个元素进行降序排序(问题保持不变)。
    2. 反向构建累积和。 [1 4 3 2] => [10 9 5 2] 以获得剩余整数仍然可以达到的最大数字的上限。
    3. 使用反向累积和的边界进行修剪。

    在 Java 中:

    // assuming the numbers are positive
    // (ignore operator when parsing, line.split("[ +-]+") will do)
    public static int canReach0(int[] numbers) {
      sort(numbers, 1); // sort(array, offset) doesn't matter what algorithm
                        // for 300 elements and compared to the complexity of the rest
      int[] revSum = new int[numbers.length];
      revSum[numbers.length - 1] = numbers[numbers.length - 1];
      for (int i = numbers.length - 2; i >= 0; i--)
        revSum[i] = revSum[i + 1] + numbers[i];
      int sum = numbers[0];
      if (sum == revSum[1])
        return 0;
      return solve(numbers, 1, sum, revSum);
    }
    
    private static int solve(int[] numbers, int index, int sum, int[] revSum) {
      if (index == numbers.length - 1)
        return -1;
      int high = sum + numbers[index];
      if (high == revSum[index + 1] || 
          (high < revSum[index + 1] && solve(numbers, index + 1, high, revSum) == 0))
        return 0;
      int low = sum - numbers[index];
      if (low == -revSum[index + 1] ||
          (low > -revSum[index + 1] && solve(numbers, index + 1, low, revSum) == 0))
        return 0;
      return -1;
    }
    

    【讨论】:

      猜你喜欢
      • 2011-08-19
      • 2017-08-22
      • 2020-11-29
      • 2013-11-08
      • 2019-09-19
      • 1970-01-01
      • 1970-01-01
      • 2018-07-28
      相关资源
      最近更新 更多