/* * SubsetTree.java * * Created on January 4, 2002, 1:51 PM */ /** * * @author Curtis Eubanks * @version 1.0 */ import java.math.BigInteger; import javax.swing.JOptionPane; import java.util.StringTokenizer; public class SubsetTree { /** length of pallet */ int M; /** lengths of stereos to pack */ int[] L; /** current solution being investigated */ int[] x; /** number of nodes traversed */ int nodesTraversedCount; /** number of solutions found */ int solutionCount; /** Creates new SubsetTree */ public SubsetTree(int palletSize, int[] stereoLengths) { M = palletSize; L = stereoLengths; } public void sum() { int totalLength = 0; for (int i=0; i < L.length; i++) totalLength += L[i]; /* initialize solution array to be all zeros */ x = new int[L.length]; nodesTraversedCount = 0; solutionCount = 0; visit(0, 0, totalLength); /* be friendly and grammatically correct */ System.out.println(solutionCount + " solution" + (solutionCount == 1 ? "" : "s") + " found."); // if the number of lengths is > 31, then we cannot represent 2^L with an int. // A BigInteger can represent larger numbers. BigInteger totalPossibleNodes = BigInteger.valueOf(2).pow(L.length); System.out.println("Visited " + nodesTraversedCount + " nodes, out of a possible " + totalPossibleNodes); } /** * @param k the index into L of the current node * @param s sum of lengths used so far * @param r sum of lengths remaining to be considered * **/ private void visit(int k, int s, int r) { // NOTE: in this implementation, values in solution vector x after index // k are not valid --- they contain garbage. int L_k = L[k]; /* length of current stereo */ boolean lastItem = (k == L.length - 1); /* true if the current item is the last one */ nodesTraversedCount++; /* pruning rule 1: are we done? */ if (s + L_k == M || (lastItem && s + L_k < M)) { x[k] = 1; solutionCount++; printSolution(k); } if (lastItem) return; /* otherwise, recurse with right node and/or left node */ /* pruning rule 2 */ if (s + L_k + L[k+1] <= M) { x[k] = 1; /* generate left node */ visit(k+1, s + L_k, r - L_k); } /* pruning rule 3 */ if (s + r - L_k >= M && s + L[k+1] <= M) { x[k] = 0; /* generate right node */ visit(k+1, s, r - L_k); } } private void printSolution(int k) { int i; System.out.print(" [ "); for (i = 0; i <= k; i++) { if (x[i] != 0) { System.out.print(L[i] + " "); } } System.out.println("]"); } /** * @param args the command line arguments. The first is the pallet width (M). All subsequent arguments are the lengths of stereos, which must be in non-decreasing order. */ public static void main (String args[]) { if (args.length > 1) { int palletSize = Integer.parseInt(args[0]); int[] inputLengths = new int[args.length-1]; for (int i=1; i < args.length; i++) inputLengths[i-1] = Integer.parseInt(args[i]); SubsetTree t = new SubsetTree(palletSize, inputLengths); t.sum(); } else { System.err.println("Please specify pallet length followed by lengths of stereos. For example, \"java SubsetTree 30 2 3 5 15 20\""); System.exit(-1); /* return error code to OS */ } } }