我必须获得不超过限制的一些数字的最高和。
例如,对于具有5、7、14和限制13的示例,我必须选择5和7。
这个例子只有3个数字,但我必须能够用更多的数字来做到这一点。
是否有图书馆或方法可以做到这一点?
最佳答案
我假设允许的输入为正整数。对于您的问题示例,这将返回[7, 5]
。
public class Knapsack {
private class State {
State previousState = null;
int value = 0;
}
public List<Integer> solve(List<Integer> list, int limit) {
// validate input
if (limit < 0) {
throw new IllegalArgumentException();
}
if (list == null) {
throw new IllegalArgumentException();
}
for (Integer i: list) {
if (i == null || i.intValue() <= 0) {
throw new IllegalArgumentException();
}
}
// if the limit is 12, then 0 through 12 inclusive are valid amounts
State[] states = new State[limit + 1];
// the state at position x represents a way of achieving a sum of x
// if a state is null it means we can't get that sum, for example in your
// question there's no way to get a sum of 11 with any combination of inputs
// base state -- we can always get a sum of zero if we just take nothing
states[0] = new State();
// build up more states
for (Integer i: list) {
// iterate through the states backwards
// if we iterate forwards we'll encounter any changes we make to the list
// during the iteration, which has the effect of taking the same number
// multiple times
for (int j = limit - i.intValue(); j >= 0; --j) {
if (states[j] != null) {
State newState = new State();
newState.previousState = states[j];
newState.value = i.intValue();
states[i.intValue() + j] = newState;
}
}
}
// find the best state
State s = null;
for (int i = limit; i >= 0; --i) {
if (states[i] != null) {
// if all you care about is the best achievable sum, you can just
// return i here
s = states[i];
break;
}
}
// build the list of numbers
List<Integer> ret = new ArrayList<Integer>();
while (s.previousState != null) {
// this will add them backwards, change to add to the beginning of the list
// to preserve the same order as the input
ret.add(Integer.valueOf(s.value));
s = s.previousState;
}
return ret;
}
public static void main(String[] arg) {
List<Integer> list = new ArrayList<Integer>();
for (int i: new int[] { 5, 7, 9 }) {
list.add(Integer.valueOf(i));
}
int limit = 13;
Knapsack k = new Knapsack();
System.out.println(k.solve(list, limit));
}
}
关于java - 最大限度地增加总和,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/15935619/