【问题标题】:Algorithm for Adding/Subtracting numbers to find if number can be made?添加/减去数字以查找是否可以制作数字的算法?
【发布时间】:2014-02-28 02:32:52
【问题描述】:

我想知道是否有一种有效的预制算法来确定一组数字的和/差是否可以等于不同的数字。示例:

5、8、10、2,使用 + 或 - 等于 9。 5 - 8 = -3 + 10 = 7 + 2 = 9

如果有一个预先存在的算法,它叫什么。如果没有,我可以弄清楚如何对其进行编程,尽管它可能效率不高。

谢谢!

【问题讨论】:

  • 与“背包问题”相关的声音
  • 如果你必须使用所有的数字,那么你有 NP-hard partition problem。如果您不必使用所有数字,这似乎是一个修改后的子集和问题,并且可能也是 NP-hard。
  • (幸运的是,有相当不错的算法可以解决分区问题。见stackoverflow.com/questions/5741242/…

标签: algorithm numbers computer-science addition


【解决方案1】:

是的,这基本上是背包问题,但可以使用动态规划在伪多项式时间内计算。

我是几个月前做的,所以如果你想实现它,也许这个 java 代码可以帮助你:

public void solve() {
    while (this.isEnd() == false) {
        int priceSum = this.getItemsInstance().getTotalPrice()/divide;
        int numOfItems = this.getItemsInstance().itemCount();
        int maxWeight = this.getItemsInstance().getMaxWeight();

        int[][] array = new int[numOfItems + 1][priceSum + 1];
        boolean[][] arrayCounted = new boolean[numOfItems + 1][priceSum + 1];

        for (int i = 0; i < numOfItems + 1; i++) {
            array[i][0] = 0;
            arrayCounted[i][0] = true;
        }

        int max = 0;
        int price = 0;
        for (int j = 1; j < priceSum + 1; j++) {
            for (int i = 1; i < numOfItems + 1; i++) {
                int temp = W(i, j, array, arrayCounted);
                if (temp <= maxWeight) {
                    max = temp;
                    price = j;
                }
            }
        }
    }
}

private int W(int i, int c, int[][] array, boolean[][] arrayCounted) {
    if (c < 0) {
        return MAX_PRICE / divide;
    }
    if (i == 0) {
        if (c == 0) {
            return 0;
        } else {
            return MAX_PRICE / divide;
        }
    }

    if (arrayCounted[i][c]) {
        return array[i][c];
    }

    arrayCounted[i][c] = true;
    array[i][c] = Math.min(W(i - 1, c, array, arrayCounted), W(i - 1, c - this.items[i - 1].price/divide, array, arrayCounted) + this.items[i - 1].weight);
    return array[i][c];
}

【讨论】:

    【解决方案2】:

    如果问题是通过添加或减去列表/数组的每个元素来找到给定的数字,则它不是 NP 问题。如果你考虑AP。这是 C++ 中的示例代码

        int Np( int mn, list<int>a, int c )
    {
        int size = a.size(), rst = 0, maxI = 0;
        std::list<int>::iterator it;
        while( size > c )
        {
            a.sort();
            maxI += a.back();
            a.pop_back();
            rst = 0;
            for( auto ele : a )
            {
               rst += ele;
                cout << rst << endl;
            }
            if( (rst - maxI) == mn or (maxI - rst) == mn or (maxI + rst) == mn )
            {
                return mn;
            }
            size--;
        }
       return rst; 
    }
    

    这应该会有所帮助。我想。

    【讨论】:

      【解决方案3】:

      我实际上写了一个简单的java程序,我实际上并不知道背包策略。这是我自己的解决方案。希望这会有所帮助

      import java.util.ArrayList;
      import java.util.List;
      
      public class Puzzle {
      
          public static void main(String[] args) {
      
              int targetNumber = 0;
              int min = 2147483647;
      
              int[] numbers = {-10, -30, -20, -50};
              //int[] numbers = {0,0,0,0};
              //int[] numbers = {7, 2, 10};
              //int[] numbers = {1, 2, 3, 4, 5};
              //int[] numbers = {1000, 2, 3, 4, 100};
              char set[] = {'+', '-'};
              min = getNumberClosestToTarget(numbers, set, min, targetNumber);
              System.out.println(String.format(" %d is closest to %d", min, targetNumber));
          }
      
          private static int getNumberClosestToTarget(int[] numbers, char[] set, int min, int targetNumber) {
      
              List<String> operators = new ArrayList<>();
      
              computeAllOperatorsCombination(set, "", set.length, numbers.length - 1, operators);
      
              for (String operatorString : operators) {
                  String[] ops = operatorString.split("");
                  int sum = computeSum(numbers, ops, numbers.length - 1);
                  min = getClosestToTarget(min, targetNumber, sum);
              }
      
              return min;
          }
      
      
          static int computeSum(int[] numbers, String[] operators, int index) {
      
              int result = numbers[index];
      
              if (index == 0) {
                  return result;
              } else {
                  switch (operators[index - 1]) {
                      case "+":
                          return computeSum(numbers, operators, index - 1) + result;
                      case "-":
                          return computeSum(numbers, operators, index - 1) - result;
                  }
      
                  return result;
              }
          }
      
          static void computeAllOperatorsCombination(char set[], String prefix, int n, int k, List<String> result) {
              if (k == 0) {
                  result.add(prefix);
                  return;
              }
      
              for (int i = 0; i < n; i++) {
                  String newPrefix;
                  newPrefix = prefix + set[i];
                  computeAllOperatorsCombination(set, newPrefix, n, k - 1, result);
              }
          }
      
          private static int getClosestToTarget(int min, int targetNumber, int r) {
              int distance = Math.abs(targetNumber - r) < Math.abs(r - targetNumber) ? Math.abs(targetNumber - r) : Math.abs(r - targetNumber);
              if (distance < Math.abs(min)) {
                  min = distance;
      
                  if (r < 0) {
                      min = -distance;
                  }
              }
              return min;
          }
      }
      

      【讨论】:

        猜你喜欢
        • 2021-12-13
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-09-08
        • 1970-01-01
        • 2020-06-16
        • 1970-01-01
        相关资源
        最近更新 更多