Search code examples
c++algorithmpuzzle

C++ Chocolate Puzzle


Let's say I have N chocolates that have to be packed into exactly P boxes in the order they arrive. Each chocolate also has a number of calories X and each box has a capacity K which has to be less than or equal to 3*sum(x1, x2, ..., xn) + max(x1, x2, ..., xn)^2 - min(x1, x2, ..., xn)^2.

In the task I'm given N, P and X for each chocolate and I have to figure out the lowest possible K. Could anyone help me on this (not looking for a solution just for some hints regarding the problem)?

Example: N = 8, P = 3, X = {1, 4, 5, 6, 3, 2, 5, 3}

K for first three chocolates = 3*(1+4+5) + 5^2 - 1^2 = 54
K for next two chocolates = 3*(6+3) + 6^2 - 3^2 = 54
K for last three chocolates = 3*(2+5+3) + 5^2 - 2^2  = 51

Lowest possible K = 54

So the goal is to find the best combination using exactly P boxes that has the lowest K.

Thanks!


Solution

  • Here is how I would solve this in Java:

    import java.util.HashMap;
    import java.util.Map;
    import java.util.Random;
    
    public class ChocolatePuzzle {
        private static final Map <String, Integer> solutions =
            new HashMap <String, Integer> ();
    
        private static final Map <String, Integer> bestMoves =
                new HashMap <String, Integer> ();
    
        private static int [] x;
    
        private static int k (int from, int to)
        {
            int sum = x [from];
            int max = x [from];
            int min = x [from];
            for (int i = from + 1; i < to; i++)
            {
                sum += x [i];
                max = Math.max (max, x [i]);
                min = Math.min (min, x [i]);
            }
    
            return sum * 3 + max * max - min * min;
        }
    
        public static int solve (int n, int p)
        {
            String signature = n + "," + p;
            Integer solution = solutions.get (signature);
            if (solution == null)
            {
                solution = Integer.valueOf (doSolve (n, p, signature));
                solutions.put (signature, solution);
            }
            return solution.intValue ();
        }
    
        public static int doSolve (int n, int p, String signature)
        {
            if (p == 1)
            {
                bestMoves.put (signature, Integer.valueOf (x.length - n));
                return k (n, x.length);
            }
            else
            {
                int result = Integer.MAX_VALUE;
                int bestMove = 0;
    
                int maxI = x.length - n - p + 1;
                for (int i = 1; i <= maxI; i++)
                {
                    int k = Math.max (k (n, n + i), solve (n + i, p - 1));
    
                    if (k < result)
                    {
                        result = k;
                        bestMove = i;
                    }
                }
    
                bestMoves.put (signature, Integer.valueOf (bestMove));
    
                return result;
            }
        }
    
        public static void main(String[] args) {
            int n = 20;
            int p = 5;
            x = new int [n];
    
            Random r = new Random ();
            for (int i = 0; i < n; i++)
                x [i] = r.nextInt (9) + 1;
    
            System.out.println("N: " + n);
            System.out.println("P: " + p);
            System.out.print("X: {");
            for (int i = 0; i < n; i++)
            {
                if (i > 0) System.out.print (", ");
                System.out.print (x [i]);
            }
            System.out.println("}");
    
            System.out.println();
    
            int k = solve (0, p);
    
            int o = 0;
            for (int i = p; i > 0; i--)
            {
                int m = bestMoves.get (o + "," + i);
    
                System.out.print ("{");
                for (int j = 0; j < m; j++)
                {
                    if (j > 0)
                        System.out.print (", ");
                    System.out.print (x [o + j]);
                }
                System.out.print ("} (k: ");
                System.out.print(k (o, o + m));
                System.out.println (")");
    
                o += m;
            }
    
            System.out.println("min(k): " + k);
        }
    }
    

    Probably you could find some useful tips in this code.

    Sample input:

    N: 20
    P: 5
    X: {1, 7, 6, 6, 5, 5, 7, 9, 1, 3, 9, 5, 3, 7, 9, 1, 4, 2, 4, 8}
    

    Sample output:

    {1, 7, 6, 6} (k: 108)
    {5, 5, 7, 9} (k: 134)
    {1, 3, 9, 5} (k: 134)
    {3, 7, 9} (k: 129)
    {1, 4, 2, 4, 8} (k: 120)
    min(k): 134