/** * Stacking Numbers * Problem 3, AIC 2003 * C# Sample Solution (slow but simple, scores 50%) */ /** * This solution simply runs through all possible choices for the six * numbers at the bottom of the pyramid. From these it selects the * combination that gives the highest possible score (number at the * top of the pyramid). * * If there are N numbers to choose from in the input set, we expect * a bit under N^6 combinations overall for large N. If N = 32 (the * maximum case allowed in the problem statement) then this is about * 1,000,000,000 combinations which is too many for a 2s time limit. */ using System; using System.IO; using System.Text; public class StackingNumbers { // Constants from the problem statement: public const int MAXSET = 32; // Maximum size of the input set // Variables holding the input data: private static int modBase; // Modular base to use with addition private static int[] set // Set of available starting numbers = new int[MAXSET]; // to choose from private static int setSize; // Number of available starting numbers // to choose from // Variables describing the current and best arrangements: private static int[] start // The six numbers at the bottom of = new int[6]; // the pyramid private static int[] ans // The six numbers that give the best = new int[6]; // possible final score private static int bestScore; // The best possible final score /** * Reads the next token from the input file. * Tokens are separated by whitespace, i.e., spaces, tabs and newlines. * If end-of-file is reached then an empty string is returned. */ private static String readToken(StreamReader sr) { StringBuilder ans = new StringBuilder(); int next; // Skip any initial whitespace. next = sr.Read(); while (next >= 0 && char.IsWhiteSpace((char)next)) next = sr.Read(); // Read the following token. while (next >= 0 && ! char.IsWhiteSpace((char)next)) { ans.Append((char)next); next = sr.Read(); } return ans.ToString(); } /** * Calculates the score at the top of the pyramid from the six numbers * currently at the bottom of the pyramid. The numbers at the bottom of * the pyramid are start[0..5]. */ private static int score() { int left = (start[0] + (4 * start[1]) + (6 * start[2]) + (4 * start[3]) + start[4]) % modBase; int right = (start[1] + (4 * start[2]) + (6 * start[3]) + (4 * start[4]) + start[5]) % modBase; return left * right; } /** * The main program. */ public static void Main(string[] args) { // Read the input data. StreamReader sr = new StreamReader("stackin.txt"); modBase = int.Parse(readToken(sr)); setSize = int.Parse(readToken(sr)); for (int i = 0; i < setSize; i++) set[i] = int.Parse(readToken(sr)); sr.Close(); // Search through all possible combinations. // This is done with six nested for loops, one for each number at // the bottom of the pyramid. // Note that we ensure at each stage that these six numbers are // distinct. bestScore = -1; int i0, i1, i2, i3, i4, i5; int currScore; for (i0 = 0; i0 < setSize; i0++) { start[0] = set[i0]; for (i1 = 0; i1 < setSize; i1++) { if (i1 == i0) continue; start[1] = set[i1]; for (i2 = 0; i2 < setSize; i2++) { if (i2 == i1 || i2 == i0) continue; start[2] = set[i2]; for (i3 = 0; i3 < setSize; i3++) { if (i3 == i2 || i3 == i1 || i3 == i0) continue; start[3] = set[i3]; for (i4 = 0; i4 < setSize; i4++) { if (i4 == i3 || i4 == i2 || i4 == i1 || i4 == i0) continue; start[4] = set[i4]; for (i5 = 0; i5 < setSize; i5++) { if (i5 == i4 || i5 == i3 || i5 == i2 || i5 == i1 || i5 == i0) continue; start[5] = set[i5]; // We have a selection of six starting numbers. // See if the resulting score is better than // we've seen so far. currScore = score(); if (currScore > bestScore) { bestScore = currScore; for (int i = 0; i < 6; i++) ans[i] = start[i]; } } } } } } } // Output the best solution that was found. StreamWriter sw = new StreamWriter("stackout.txt"); sw.WriteLine(bestScore); sw.WriteLine(ans[0] + " " + ans[1] + " " + ans[2] + " " + ans[3] + " " + ans[4] + " " + ans[5]); sw.Close(); } }