某人的饭量为T,有n份体积分别为t1, t2, ... tn的美食,能否从n份美食中挑选若干份,使得恰好吃饱,也不浪费食物,求出所有满足条件的选择。
例: 请输入饭量T:T=10 请输入食品份数n:n=6 请输入6份食品的体积:1, 8, 4, 3, 5, 2 输出:可得到四组解:(1,4,3,2); (1,4,5); (8,2); (3,5,2)。
我的想法是设计一个自定义的整形栈来解决,但是没有成功。主要问题不知道如何将栈顶的数弹出, (1,4,5)和(3,5,2)两组解搞不出来。
PHP中文网2017-04-17 11:12:31
First abstract the problem:
Given a set C and a threshold m, it is required to find all eligible subsets S of C such that the sum of all elements of S is m.
This problem can actually be solved through dynamic programming. The solution process can be in recursive and non-recursive forms, and the so-called recursive form (special case: [tail recursion], which can be converted into a non-recursive form through compiler optimization) is actually a process in which the call stack repeatedly calls itself directly or indirectly. . Therefore, it can be solved completely through the data structure of the stack, and this solution, to a certain extent, is to expand the recursive solution process through the stack. Without further ado, let’s talk about the code (I haven’t written C for a long time, so I wrote an implementation in Java language. In order to intuitively reflect the solution process, some conventional data verification is ignored in the code):
package com.lee.test;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public class PackageProblem {
public static void main(String[] args) {
int[] problemSpace = {1, 8, 4, 3, 5, 2};
int threshold = 10;
printProblem(problemSpace, threshold);
printSolution(solve(problemSpace, threshold));
}
private static void printProblem(int[] problemSpace, int threshold) {
System.out.println("Problem Space : "+Arrays.toString(problemSpace));
System.out.println("Problem threshold : "+threshold);
}
private static void printSolution(List<int[]> solutions) {
System.out.println("Solutions : ");
if(solutions == null || solutions.size() < 1) {
System.out.println("no solution.");
}else {
for(int[] solution : solutions) {
System.out.println(Arrays.toString(solution));
}
}
}
static class Element {
int index;
int value;
Element(int index, int value) {
this.index = index;
this.value = value;
}
}
static class Stack {
private Element[] elements;
private int top;
private int sum;
Stack(int capacity) {
elements = new Element[capacity];
top = -1;
sum = 0;
}
void push(int index, int value) {
if(top == elements.length - 1) {
throw new IllegalStateException("stack is already full.");
}
elements[++top] = new Element(index, value);
sum += value;
}
Element pop() {
if(top == -1) {
throw new IllegalStateException("stack is already empty.");
}
Element element = elements[top--];
sum -= element.value;
return element;
}
boolean isEmpty() { return top == -1; }
int sum() { return sum; }
int[] snapshot() {
int[] snapshot = new int[top+1];
for(int i=0; i<= top; i++) {
snapshot[i] = elements[i].value;
}
return snapshot;
}
}
private static List<int[]> solve(int[] problemSpace, int threshold) {
if(problemSpace == null) {
throw new NullPointerException("problem space is null.");
}
List<int[]> solutions = new ArrayList<int[]>();
if(problemSpace.length < 1) {
return solutions;
}
Stack stack = new Stack(problemSpace.length);
stack.push(0, problemSpace[0]);
int index = 0;
while(true) {
int sum = stack.sum();
if(sum >= threshold) {
if(sum == threshold) {
solutions.add(stack.snapshot());
}
index = stack.pop().index;
}
if(index < problemSpace.length - 1) {
stack.push(++index, problemSpace[index]);
}else {
if(sum < threshold) { stack.pop(); }
if(stack.isEmpty()) { break; }
index = stack.pop().index;
}
}
return solutions;
}
}
PS: I ran it myself and it should be OK. If you have any questions, please leave a message