English 中文(简体)
建立一份所有可能百分比的项目清单?
原标题:Creating a list of all possible percentages of items?

My goal is to give the program a few items(Strings), a range, and target percent and let it give me all possible percentages of each item. For example, Imagine you go to the grocery store and have a basket of Apples & Pears you want to know all the percentages you could have using ALL items(not a full solution, I m doing this by hand): {Apple:50, Pears:50}, {Apple:75, Pears:25}, {Apple:90, Pears:10},etc.

If I do the same thing with a range of 20-50(meaning the highest value a single item can have is 50% and the lowest 20%) then the only result is: {Apple:50, Pears:50} (since there are only 2 items and it cannot exceed 50% weight)

我认为它也有类似的特质,比如“背包问题 ” ( knapsack problem)与“背包问题 ” ( knapsack problem)没有关联到这些物品的价值/重量(但就像“背包问题 ” ( knapsack problem ), 试图将物品与“背包” 匹配到“背包项目 ” ( knapsack problem ) 。 我试图将价值与“目标 ” ( 百分比, 100% ) 。 我也很难应用一般动态的编程想法, 也因为我无法找出如何打破问题( 典型的背包问题正在形成结果, ” 和“缓冲” 的结果再利用, 但如果我有一个 X 项清单, 我需要所有X 物品在范围内使用 ) 。

我可以通过粗力做到这一点, 但我并不觉得它是有效的, 因为它只是试探一切我正在使用的界限, 根本用不着用它来提高效率(例如,苹果为75%,那么Pear就没有任何理由超过25%)。. 范围是列表、范围和目标的百分之二十五的大小。 我可能有20-30个清单项目,范围在5-20或大约50个项目之间,范围在1-5之间。 或任何我之间想要玩弄的,我可以得到的尽可能快的多少完整结果。 我还没有在问题中显示目标-%的部分,因为我可以设置它,一旦我了解如何解决问题,但基本上所有的例子都假定是百分之百,但有时你的篮子里已经有20%的橘子,看看如何用苹果/梨来填满其余的百分之八十。

我的问题是,我怎样才能解决这个问题(使用任何想法的逻辑、例子或代理问题)? 动态编程是否适合这一问题? 动态编程是否适合这一问题,或者我无法将它分成小块的问题(因为它总是包括列表中的所有项目,所以没有建立起来 )? 如果有人能指向我正确的方向,我愿意研究任何可能有所帮助的议题(在花了2天时间试图弄清楚这一点之后,我不确定动态编程路线是否正确 ) 。 是否还有这类问题的名称(我查了Knapack问题、整形分割问题、组合法问题,但没有人认为合适 )?

我的野蛮武力方法(其实不像预期的那样有效, 但也许能让你们了解野蛮武力方法):

import java.util.ArrayList;
import java.util.Arrays;


public class brute_force_percent_returner {
    static String[] data = new String[]{"Apple", "Pears"};
    static int[] coeff = new int[data.length];
    static ArrayList<int[]> queue = new ArrayList<int[]>();

    public static void main(String[] args) {
        System.out.println("Starting");
        recursion(0,data);
        for (int[] item : queue) {
            for (int item2 = 0; item2<data.length; item2++) {
                System.out.print(data[item2] + " = " + item[item2] + " ");
            }
            System.out.println();
        }
    }

    private static void recursion(int k, String[] data2) {
        // this is not exactly working
        for (String item: data2) {
            for (int x = 0; x<5;x++) {
                int[] coeff_temp = Arrays.copyOf(coeff, coeff.length);
                coeff_temp[k] = x;
                queue.add(coeff_temp);
            }
        }
        if (k == data.length-1) {
            return;
        } else {
            recursion(k+1, data2);
        }
    }
}

如果它有助于我试图创造的解决方案 在某种程度上是基于这个问题(它是一个背包问题,但对于大量变数来说似乎超快,但在此情况下,它处理的项目是清单中的项目,而对于我来说,清单只是字符串):

public class TurboAdder {
    private static final int[] data = new int[] { 5, 10, 20, 25, 40, 50 };

    private static class Node {
        public final int index;
        public final int count;
        public final Node prevInList;
        public final int prevSum;
        public Node(int index, int count, Node prevInList, int prevSum) {
            this.index = index;
            this.count = count;
            this.prevInList = prevInList;
            this.prevSum = prevSum;
        }
    }

    private static int target = 100;
    private static Node sums[] = new Node[target+1];

    // Only for use by printString.
    private static boolean forbiddenValues[] = new boolean[data.length];

    public static void printString(String prev, Node n) {
        if (n == null) {
            System.out.println(prev);
        } else {
            while (n != null) {
                int idx = n.index;
                // We prevent recursion on a value already seen.
                if (!forbiddenValues[idx]) {
                    forbiddenValues[idx] = true;
                    printString((prev == null ? "" : (prev+" + "))+data[idx]+"*"+n.count, sums[n.prevSum]);
                    forbiddenValues[idx] = false;
                }
                n = n.prevInList;
            }
        }
    }

    public static void main(String[] args) {
        for (int i = 0; i < data.length; i++) {
            int value = data[i];
            for (int count = 1, sum = value; count <= 100 && sum <= target; count++, sum += value) {
                for (int newsum = sum+1; newsum <= target; newsum++) {
                    if (sums[newsum - sum] != null) {
                        sums[newsum] = new Node(i, count, sums[newsum], newsum - sum);
                    }
                }
            }
            for (int count = 1, sum = value; count <= 100 && sum <= target; count++, sum += value) {
                sums[sum] = new Node(i, count, sums[sum], 0);
            }
        }
        printString(null, sums[target]);

    }
}
最佳回答

这听起来像家庭作业,所以我特别不愿意 帮助你太多, 但这里有一个方法。

定义范围,绘制几个散列地图,例如

lower bounds = {apples  => 20, pears => 40,  oranges => 0}
upper bounds = {apples  => 50, pears => 100, oranges => 30}

如果您仔细想一想, 每一个最终( 有效) 组合至少会拥有下拉地图定义的内容。 所以调用基数组合 。

下一步, 找出每种类型的理论最大值, 您可能添加到基数组合中。 这只是另外一张映射图

{apples  => 30, pears => 60,  oranges => 30}

您可以向基准地图添加多少项的总项目, 即 100 个, 即所有较低约束值的总和, 例如, 其 40 个 。

现在,您需要生成组合。 您可能会发现重现是最简单的方法。 错误地展示了其余的算法, 包括伪代码和硬编码, 来提高清晰度, 尽管您需要写一个通用的循环版本 。

totalItemsToAdd = 40 //as calculated via baseCombo.sumOfEntries()


for (i=0; i<maxApples; i++) {
    combo = clone the base combination
    combo.apples += i;
    remainingItemsToAdd = totalItemsToAdd - i;
    if (remainingItemsToAdd > 0) {
        for (j=0; j<maxPears; j++) {
            combo.pears += j;
            // and so on, recursively
        }
    }

    results.append(combo)
}

提醒它如何只通过跟踪每个组合中有多少项可能生成有效组合。 因此, 这不会是野蛮的力量, 它实际上会做生成组合所需的最起码的工作 。

问题回答

我相信武力是最好的方法-至少我也会这样做(这绝不是一回事...)。

这里试图用我的工作方式(虽然我还没有用 weights No 高值测试过它), 这样做的根据是,你对重量的组合而不是重量的变换感兴趣,尽管开关相对简单。

public static Set<int[]> getPossiblePercentageWeights(int weightsNo, int min, int max){
  return recusiveFixWeight(weightsNo, 100, min, max);
}

private static Set<int[]> recusiveFixWeight(int weightsNo, int sum, int min, int max){
  Set<int[]> weightsSet = new LinkedHashSet<int[]>();
  if (weightsNo>2){
    for (int iWeight=min; iWeight<=max; iWeight++){
      Set<int[]> subSet = recusiveFixWeight(weightsNo-1, sum-iWeight, min, iWeight);
      for (int[] subWeights : subSet){
        int[] weights = new int[weightsNo];
        weights[0] = iWeight;
        System.arraycopy(subWeights, 0, weights, 1, subWeights.length);
        weightsSet.add(weights);
      }
    }
  } else {
    int iMax = Math.min(max, sum/weightsNo);
    for (int iWeight=min; iWeight<=iMax; iWeight++){
      int jWeight = sum-iWeight;
      if (jWeight>=min && jWeight<=max){
        weightsSet.add(new int[]{iWeight,jWeight});
      }
    }
  }
  return weightsSet;
}

尽管如此,在查看了结果之后,它似乎应该有一种算法来确定在 weights No min /max 的情况下,有多少重量Ssets存在。 从这个算法来看,用可能的数值填充它们应该相当简单。 也就是说, 我目前还不能完全弄清楚。 (或者说,它是否比粗力方法更快... ) 。





相关问题
Spring Properties File

Hi have this j2ee web application developed using spring framework. I have a problem with rendering mnessages in nihongo characters from the properties file. I tried converting the file to ascii using ...

Logging a global ID in multiple components

I have a system which contains multiple applications connected together using JMS and Spring Integration. Messages get sent along a chain of applications. [App A] -> [App B] -> [App C] We set a ...

Java Library Size

If I m given two Java Libraries in Jar format, 1 having no bells and whistles, and the other having lots of them that will mostly go unused.... my question is: How will the larger, mostly unused ...

How to get the Array Class for a given Class in Java?

I have a Class variable that holds a certain type and I need to get a variable that holds the corresponding array class. The best I could come up with is this: Class arrayOfFooClass = java.lang....

SQLite , Derby vs file system

I m working on a Java desktop application that reads and writes from/to different files. I think a better solution would be to replace the file system by a SQLite database. How hard is it to migrate ...