import java.io.*; import java.util.*; /* Basic solution idea We know the number of hunters(H) and the number of treasures(T). Imagine a base H number with T digits. Example: H=2 T=4, a number running from 0000 to 1111. Since its a base 2 number (binary), 1 is the highest possible digit value. Each digit represents a treasure, and each digit value represents which hunter the treasure is assigned to. Example: 0101 means Hunter #0 gets treasure #0 and #2, Hunter #1 gets treasure #1 and #3. Therefore, by starting the "Number" at zero and incrementing by one to its max value, every possible digit combination represents every possible treasure distribution. All we need to do is compute the difference between the max and min perceived values by the hunters for each possible distribution and save the "Number value" which produces the lowest difference value. */ public class Treasure { public static void main(String args[]) { BufferedReader in = new BufferedReader(new InputStreamReader(System.in)); String line; int numTreasure = 0; int numHunter = 0; int loopCounter = 0; Hunter[] hunters = new Hunter[6]; try { while ((line = in.readLine()) != null) { if (line.equals("START")) { numTreasure = 0; numHunter = 0; } else if (line.equals("END")) { solve(hunters,numHunter,numTreasure); loopCounter = 0; } else { //Ignore first two lines of input set indicating number of treasures and hunters. //This solution counts the number of hunters as it parses their "value assignments". //Or perhaps the number of treasures/hunters wasn't part of the input set when I //first wrote this solution and I am just ignoring that part of the input. :) if (loopCounter == 0) { loopCounter++; } else if (loopCounter == 1) { loopCounter++; } else { //this branch gets executed for every "perceived value" input line numHunter++; hunters[numHunter-1] = new Hunter(numHunter-1); numTreasure=0; StringTokenizer st = new StringTokenizer(line); while (st.hasMoreTokens()) { numTreasure++; hunters[numHunter-1].addWorth(Integer.parseInt(st.nextToken())); } } } }//end while } catch (IOException e) { System.out.println(e); } } //Function Name: solve //Purpose: For each input data set, determine the optimal treasure distribution // and output it. //Description: This method uses the Counter class. Each digit represents a treasure. // The value of the digit represents which hunter will get it. So by // incrementing through every possible value of the Counter, every // possible treasure distribution can have the "treasure value difference" // calculated for it. public static void solve(Hunter[] hunters, int numH, int numT) { int i; int minDifference = -1; //minimum difference, best solution found int pDifference = 0; //perceived difference between max and min hunter values String solution = ""; //Subtract one from numH since Counter class takes argument // representing max value of digit. //Since zero will represent a treasure hunter, each Counter // digit only needs to run from 0 to numH-1 to represent // numH treasure hunters. Counter digits = new Counter(numH-1); //Activate number of digits equal to the number of treasures for (i=0;i maxValue) maxValue = pValue; if ((pValue < minValue) || (minValue == -1)) minValue = pValue; } return (maxValue - minValue); } } /*****************************************/ /************ Counter Class ************/ /*****************************************/ //The Counter class represents a number on a // digit-by-digit level. //This number acts like a base ten number except // the leftmost number is the least significant digit. // So 80 + 1 = 90 and 90 + 1 = 01 and 9990 + 1 = 0001 // (this is an implementation detail and doesnt really matter) //This class provides the increment() method to increase // the counter value by one. //The canIncrement() method tells you if it is safe to increment // or if the max Counter value has been reached. class Counter { //-1 means inactive digit not used for current data set public int[] digit = {-1,-1,-1,-1,-1,-1,-1,-1}; //max value any digit may have public int maxDigit; //constructor function takes argument representing max value of // any digit Counter(int max) { maxDigit = max; } public void activateDigit(int index) { digit[index] = 0; } public int getDigit(int index) { return digit[index]; } //Function Name: increment //Purpose: Increments Counter object by 1 // Public and private function signatures exists. Private // version is for internal recursive use only. public void increment() { increment(0); } private void increment(int index) { // check if adding one to digit will cause a carry situation if (digit[index]+1 > maxDigit) { digit[index] = 0; //set this digit back to zero, increment next digit if (index < 7) increment(index+1); //recursion is your friend else //this should never happen if you check the canIncrement() function System.out.println("ERROR: increment overrun : "+index+" : "+toString()); } else { //just add one to the digit since it will not cause a carry situation digit[index]++; } } //Function Name: canIncrement //Purpose: returns true if Counter object can be incremented by 1, false otherwise //Description: If a digit is -1, then it can not be incremented since it is inactive. // If digit is less than maxDigit, number can obviously be incremented. // If digit not less than maxDigit, make sure next digit over can be // incremented. public boolean canIncrement() { int i; for (i=0;i<8;i++) { if (digit[i] < maxDigit) return true; else if (i==7) //i==7 means all digits are equal to maxDigit, so cant increment return false; else if (digit[i+1] == -1) //next digit is not active, so cant increment return false; } return false; //java made me put this line even though it will never be reached } //return string representation of this object for debugging purposes public String toString() { String returnStr = ""; for(int i=0;i<8;i++) { if (digit[i] != -1) returnStr += String.valueOf(digit[i]); } return returnStr; } } /*****************************************/ /************ Hunter Class ************/ /*****************************************/ class Hunter { int name; int[] worth = {-1,-1,-1,-1,-1,-1,-1,-1}; int num = 0; //The hunter needs to know which digit value number he represents // Kinda like his name.... Hunter 0, Hunter 1, so on... Hunter(int n) { name = n; } public void addWorth(int value) { worth[num] = value; num++; } public int getWorth(int index) { return worth[index]; } //calculates this hunter's total perceived value for the // current treasure distribution represented by the digits argument public int computeValue(Counter digits) { int totalValue = 0; int i; for (i=0;(digits.getDigit(i) != -1)&&(i<8);i++) { if (digits.getDigit(i) == name) { totalValue += worth[i]; } } return totalValue; } //for debugging purposes public String toString() { String returnStr = ""; for (int i=0; i