import java.util.Arrays;
import java.util.Vector;
public class ElectoralCounts {
public static void main(String[] args) {
// TODO Auto-generated method stub
int[] votes = { 9, 3, 11, 6, 55, 9, 7, 3, 3, 29, 16, 4, 4, 20, 11, 6,
6, 8, 8, 4, 10, 11, 16, 10, 6, 10, 3, 5, 6, 4, 14, 5, 29, 15,
3, 18, 7, 7, 20, 4, 9, 3, 11, 38, 6, 3, 13, 12, 5, 10, 3 };
int sum = 0;
for (int i = 0; i < votes.length; i++) {
sum += votes[i];
}
calculateMaxSum(votes, sum / 2);
}
public static void calculateMaxSum(int[] votes, int sum) {
int[][] M = new int[votes.length + 1][sum + 1];
numSolutions = new long[votes.length + 1][sum + 1];
resetNumSolutions();
for (int i = 1; i <= votes.length; i++) {
int w_i = votes[i - 1];
for (int w = 0; w <= sum; w++) {
if (w < w_i) {
M[i][w] = M[i - 1][w];
} else {
int choiceAddElement = votes[i - 1] + M[i - 1][w - w_i];
int choiceIgnoreElement = M[i - 1][w];
if (choiceAddElement > choiceIgnoreElement) {
M[i][w] = choiceAddElement;
} else {
M[i][w] = choiceIgnoreElement;
}
}
}
}
// M[votes.length][sum] = 269
PathCount(M, votes, votes.length, sum);
System.out.println(M[votes.length][sum]);
System.out.println("Num Solutions: " + numSolutions[votes.length][sum]);
System.out.println(bad_items);
// printOptArray(M);
// printNumSolutionsArray();
}
private static long path_count = 0;
private static long bad_items = 0;
private static Vector<Integer> soln = new Vector<Integer>();
private static long[][] numSolutions;
public static long PathCount(int[][] M, int[] votes, int i, int j) {
if (i < 0 || j < 0) {
bad_items++;
return 0;
}
if (numSolutions[i][j] != -1)
{
return numSolutions[i][j];
}
if (i == 0 && j == 0) {
// printOutSolution();
path_count++;
return 1;
} else {
int w = j;
int w_i = votes[i - 1];
if (w < w_i) {
M[i][w] = M[i - 1][w];
numSolutions[i][j] = PathCount(M, votes, i - 1, w);
} else {
int choiceAddElement = votes[i - 1] + M[i - 1][w - w_i];
int choiceIgnoreElement = M[i - 1][w];
if (choiceAddElement == choiceIgnoreElement) {
numSolutions[i][j] = PathCount(M, votes, i - 1, w);
soln.add(w_i);
numSolutions[i][j] += PathCount(M, votes, i - 1, w - w_i);
soln.removeElement(w_i);
} else {
if (choiceAddElement > choiceIgnoreElement) {
M[i][w] = choiceAddElement;
soln.add(w_i);
numSolutions[i][j] = PathCount(M, votes, i - 1, w - w_i);
soln.removeElement(w_i);
} else {
M[i][w] = choiceIgnoreElement;
numSolutions[i][j] = PathCount(M, votes, i - 1, w);
}
}
}
return numSolutions[i][j];
}
}
private static void printOutSolution() {
int sum = 0;
for (int k = 0; k < soln.size(); k++) {
sum += soln.elementAt(k);
}
Object[] solnArray = soln.toArray();
// Arrays.sort(solnArray);
System.out.println(sum + ": " + Arrays.toString(solnArray));
// soln.clear();
}
private static void printOptArray(int[][] M) {
for (int i = 0; i < M.length; i++) {
System.out.println("");
for (int j = 0; j < M[i].length; j++) {
System.out.print(M[i][j] + " ");
}
}
}
private static void printNumSolutionsArray() {
for (int i = 0; i < numSolutions.length; i++) {
System.out.println("");
for (int j = 0; j < numSolutions[i].length; j++) {
System.out.print(numSolutions[i][j] + " ");
}
}
}
private static void resetNumSolutions() {
for (int i = 0; i < numSolutions.length; i++) {
for (int j = 0; j < numSolutions[i].length; j++) {
numSolutions[i][j] = -1;
}
}
}
}