Advertisement
nikolov_k

Game of Trolls - algorithm

Dec 17th, 2012
111
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C# 13.24 KB | None | 0 0
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Text;
  4. using System.Diagnostics;
  5. using System.IO;
  6.  
  7. class Algorithm
  8. {
  9.     static int c, n, maxMove;
  10.     static int[,] field;
  11.     static Data maxElement;
  12.     static float bestResult = float.MaxValue;
  13.     static StringBuilder result = new StringBuilder(12000);
  14.     static float acceleratorStep = 0f;
  15.     static float acceleratorStat = 1f;
  16.     static double secondsForLoop = 0;
  17.  
  18.     // Information about possible moves and their result
  19.     struct Data
  20.     {
  21.         public int row;
  22.         public int col;
  23.         public float coefficient;
  24.         public int move;
  25.     }
  26.  
  27.  
  28.     static void Main()
  29.     {
  30.         Stopwatch totalTime = new Stopwatch();
  31.         Stopwatch turnTime = new Stopwatch();
  32.         totalTime.Start();
  33.         InputField();
  34.         //InputFileConsole();
  35.         int startSum = CalculateSum();
  36.         bool firstTurn = true;
  37.         do
  38.         {
  39.             if (firstTurn)
  40.             {
  41.                 turnTime.Start();
  42.                 CalculateCoefficients();
  43.             }
  44.             else
  45.             {
  46.                 CalculateCoefficients();
  47.             }
  48.             if (maxElement.coefficient > 0)
  49.             {
  50.                 MakeMoves(maxElement.row, maxElement.col, maxElement.move);
  51.                 maxElement.coefficient = 0;
  52.             }
  53.             else
  54.             {
  55.                 Console.WriteLine();
  56.                 JustTake();
  57.             }
  58.             if (firstTurn)
  59.             {
  60.                 turnTime.Stop();
  61.                 secondsForLoop = turnTime.Elapsed.TotalMilliseconds * c / 1000;
  62.                 CalculateAccelerators();
  63.             }
  64.             firstTurn = false;
  65.         } while ((maxMove > 0) && (totalTime.ElapsedMilliseconds < 2820));
  66.         if (maxMove > 0)
  67.         {
  68.             JustTake();
  69.         }
  70.         Console.WindowHeight = 1;
  71.         Console.WindowWidth = 14;
  72.         Console.WriteLine(result);
  73.         Console.WindowHeight = 30;
  74.         Console.WindowWidth = 40;
  75.         //int endSum = CalculateSum();
  76.         //Console.WriteLine("Result = {0}", startSum - endSum);
  77.         totalTime.Stop();
  78.         //Console.WriteLine("Time = {0}", totalTime.ElapsedMilliseconds);
  79.         //Console.WriteLine("Time = {0}", secondsForLoop);
  80.         //Console.WriteLine("Ostavashti hodove = {0}", maxMove);
  81.         //Console.WriteLine("ACCELERATOR = {0}", acceleratorStat);
  82.     }
  83.  
  84.     // This method calculates accelerator coefficient.
  85.     // Coefficient depends from first loop to make move.
  86.     // Accelerator
  87.     static void CalculateAccelerators()
  88.     {
  89.         if (secondsForLoop > 195)
  90.         {
  91.             acceleratorStat = 0.138f;
  92.         }
  93.         else if (secondsForLoop > 65)
  94.         {
  95.             acceleratorStat = 0.17f;
  96.         }
  97.         else if (secondsForLoop > 25)
  98.         {
  99.             acceleratorStat = 0.22f;
  100.         }
  101.         else if (secondsForLoop > 12)
  102.         {
  103.             acceleratorStat = 0.55f;
  104.         }
  105.         else if (secondsForLoop > 2.5d)
  106.         {
  107.             acceleratorStat = 0.8f;
  108.         }
  109.         else
  110.         {
  111.             acceleratorStat = 1f;
  112.         }
  113.     }
  114.  
  115.     // Method that calculate sum of all fields
  116.     static int CalculateSum()
  117.     {
  118.         int sum = 0;
  119.         for (int i = 0; i < n; i++)
  120.         {
  121.             for (int j = 0; j < n; j++)
  122.             {
  123.                 sum += field[i, j];
  124.             }
  125.         }
  126.         return sum;
  127.     }
  128.  
  129.     // This method just takes from matrix
  130.     static void JustTake()
  131.     {
  132.         for (int i = 0; i < n; i++)
  133.         {
  134.             for (int j = 0; j < n; j++)
  135.             {
  136.                 while ((field[i, j] > 0) && (maxMove > 0))
  137.                 {
  138.                     MakeMoves(i, j, -1);
  139.                 }
  140.             }
  141.         }
  142.     }
  143.  
  144.     // Take full input information from console
  145.     // Build matrix field[] with input information
  146.     static void InputField()
  147.     {
  148.         c = int.Parse(Console.ReadLine());
  149.         n = int.Parse(Console.ReadLine());
  150.         maxMove = c;
  151.         field = new int[n, n];
  152.         for (int row = 0; row < n; row++)
  153.         {
  154.             string rowText = Console.ReadLine();
  155.             string[] rowCells = rowText.Split(' ');
  156.             for (int col = 0; col < n; col++)
  157.             {
  158.                 field[row, col] = int.Parse(rowCells[col]);
  159.             }
  160.         }
  161.     }
  162.  
  163.     // After we have calculate moves that can destroy at least 2 towers,
  164.     //we use make moves to do this
  165.     static void MakeMoves(int row, int col, int move)
  166.     {
  167.         if (move > 0)
  168.         {
  169.             for (int i = 0; i < move; i++)
  170.             {
  171.                 //result += "put " + row + " " + col + "\n";
  172.                 result.Append("put ");
  173.                 result.Append(row);
  174.                 result.Append(" ");
  175.                 result.Append(col);
  176.                 result.Append("\n");
  177.                 maxMove--;
  178.                 CheckNeighbours(row, col, 1);
  179.             }
  180.         }
  181.         else
  182.         {
  183.             for (int i = 0; i < -1 * move; i++)
  184.             {
  185.                 result.Append("take ");
  186.                 result.Append(row);
  187.                 result.Append(" ");
  188.                 result.Append(col);
  189.                 result.Append("\n");
  190.                 maxMove--;
  191.                 CheckNeighbours(row, col, -1);
  192.             }
  193.         }
  194.         //PrintField();
  195.     }
  196.  
  197.     // Make moves and destroy all equal towers
  198.     static void CheckNeighbours(int row, int col, int move)
  199.     {
  200.         field[row, col] += move;
  201.         if (field[row, col] < 0)
  202.         {
  203.             field[row, col] = 0;
  204.         }
  205.         else
  206.         {
  207.             int height = field[row, col];
  208.             if ((row + 1 < n) && (height == field[row + 1, col]))
  209.             {
  210.                 field[row + 1, col] = 0;
  211.                 field[row, col] = 0;
  212.             }
  213.             if ((col + 1 < n) && (height == field[row, col + 1]))
  214.             {
  215.                 field[row, col + 1] = 0;
  216.                 field[row, col] = 0;
  217.             }
  218.             if ((row - 1 >= 0) && (height == field[row - 1, col]))
  219.             {
  220.                 field[row - 1, col] = 0;
  221.                 field[row, col] = 0;
  222.             }
  223.             if ((col - 1 >= 0) && (height == field[row, col - 1]))
  224.             {
  225.                 field[row, col - 1] = 0;
  226.                 field[row, col] = 0;
  227.             }
  228.         }
  229.     }
  230.  
  231.  
  232.  
  233.     // Calculate best result in one move
  234.     static float OneMoveResult(int[] neighbours, int element, int move)
  235.     {
  236.         int result = element;
  237.         float coefficient = 0f;
  238.         foreach (int neighbour in neighbours)
  239.         {
  240.             if (element + move == neighbour)
  241.             {
  242.                 result += neighbour;
  243.             }
  244.         }
  245.         if (move != 0)
  246.         {
  247.             coefficient = (float)result / (float)move;
  248.         }
  249.         if (move < 0)
  250.         {
  251.             coefficient *= -1;
  252.         }
  253.         return coefficient;
  254.     }
  255.  
  256.     // Method that calculate best coefficients for all elements in field
  257.     static void CalculateCoefficients()
  258.     {
  259.         Data element;
  260.         float maxCoefficient = 0f;
  261.         if (maxMove % 2 == 0)
  262.         {
  263.             for (int row = 0; row < n; row += 1 + (int)acceleratorStep)
  264.             {
  265.                 for (int col = 0 + (row % 2); col < n; col += 2 * (int)(1 + acceleratorStep))
  266.                 {
  267.                     if (field[row, col] > 0)
  268.                     {
  269.                         element = CalculateCoefficient(row, col);
  270.                         if (element.coefficient > maxCoefficient)
  271.                         {
  272.                             maxCoefficient = element.coefficient;
  273.                             maxElement = element;
  274.                             if (maxElement.coefficient > bestResult * acceleratorStat)
  275.                             {
  276.                                 return;
  277.                             }
  278.                         }
  279.                     }
  280.                 }
  281.             }
  282.         }
  283.         else
  284.         {
  285.             for (int row = n - 1; row >= 0; row -= 1 + (int)acceleratorStep)
  286.             {
  287.                 for (int col = n - 1 - (row % 2); col >= 0; col -= 2 * (int)(1 + acceleratorStep))
  288.                 {
  289.                     if (field[row, col] > 0)
  290.                     {
  291.                         element = CalculateCoefficient(row, col);
  292.                         if (element.coefficient > maxCoefficient)
  293.                         {
  294.                             maxCoefficient = element.coefficient;
  295.                             maxElement = element;
  296.                             if (maxElement.coefficient > bestResult * acceleratorStat)
  297.                             {
  298.                                 return;
  299.                             }
  300.                         }
  301.                     }
  302.                 }
  303.             }
  304.         }
  305.         bestResult = maxCoefficient;
  306.     }
  307.  
  308.     // Calculate best coefficient for one field
  309.     private static Data CalculateCoefficient(int row, int col)
  310.     {
  311.         int[] neighbours = new int[4];
  312.         int positiveMove = int.MaxValue;
  313.         int negativeMove = int.MinValue;
  314.         for (int i = 0; i < 4; i++)
  315.         {
  316.             switch (i)
  317.             {
  318.                 case 0:
  319.                     if (row + 1 < n)
  320.                     {
  321.                         neighbours[0] = field[row + 1, col];
  322.                     }
  323.                     break;
  324.                 case 1:
  325.                     if (col + 1 < n)
  326.                     {
  327.                         neighbours[1] = field[row, col + 1];
  328.                     }
  329.                     break;
  330.                 case 2:
  331.                     if (row - 1 >= 0)
  332.                     {
  333.                         neighbours[2] = field[row - 1, col];
  334.                     }
  335.                     break;
  336.                 case 3:
  337.                     if (col - 1 >= 0)
  338.                     {
  339.                         neighbours[3] = field[row, col - 1];
  340.                     }
  341.                     break;
  342.                 default:
  343.                     break;
  344.             }
  345.             int oneMove = neighbours[i] - field[row, col];
  346.             if ((oneMove > maxMove) || (oneMove < -maxMove))
  347.             {
  348.                 oneMove = 0;
  349.             }
  350.             if ((oneMove > 0) && (oneMove < positiveMove))
  351.             {
  352.                 positiveMove = oneMove;
  353.             }
  354.             else if ((oneMove < 0) && (oneMove > negativeMove))
  355.             {
  356.                 negativeMove = oneMove;
  357.             }
  358.         }
  359.         if (positiveMove == int.MaxValue)
  360.         {
  361.             positiveMove = 0;
  362.         }
  363.         if (negativeMove == int.MinValue)
  364.         {
  365.             negativeMove = 0;
  366.         }
  367.         Data element = new Data();
  368.         element.coefficient = 0f;
  369.         if (positiveMove == 0)
  370.         {
  371.             element.coefficient = OneMoveResult(neighbours, field[row, col], negativeMove);
  372.             element.move = negativeMove;
  373.         }
  374.         else if (negativeMove == 0)
  375.         {
  376.             element.coefficient = OneMoveResult(neighbours, field[row, col], positiveMove);
  377.             element.move = positiveMove;
  378.         }
  379.         else
  380.         {
  381.             element.coefficient = OneMoveResult(neighbours, field[row, col], negativeMove);
  382.             element.move = negativeMove;
  383.             float coefficient = OneMoveResult(neighbours, field[row, col], positiveMove);
  384.             if (coefficient > element.coefficient)
  385.             {
  386.                 element.coefficient = coefficient;
  387.                 element.move = positiveMove;
  388.             }
  389.         }
  390.         element.row = row;
  391.         element.col = col;
  392.         return element;
  393.     }
  394.  
  395.     // Next methods are used only for test
  396.     static void PrintField()
  397.     {
  398.         for (int i = 0; i < n; i++)
  399.         {
  400.             for (int j = 0; j < n; j++)
  401.             {
  402.                 Console.Write("{0,4} ", field[i, j]);
  403.             }
  404.             Console.WriteLine();
  405.         }
  406.     }
  407.     private static void InputFile()
  408.     {
  409.         StreamReader reader = new StreamReader("../../input.txt");
  410.         using (reader)
  411.         {
  412.             c = int.Parse(reader.ReadLine());
  413.             n = int.Parse(reader.ReadLine());
  414.             maxMove = c;
  415.             field = new int[n, n];
  416.             for (int row = 0; row < n; row++)
  417.             {
  418.                 string rowText = reader.ReadLine();
  419.                 string[] rowCells = rowText.Split(' ');
  420.                 for (int col = 0; col < n; col++)
  421.                 {
  422.                     field[row, col] = int.Parse(rowCells[col]);
  423.                 }
  424.             }
  425.         }
  426.     }
  427.  
  428.     private static void InputFileConsole()
  429.     {
  430.         StreamReader reader = new StreamReader("../../input.txt");
  431.         Console.SetIn(reader);
  432.         c = int.Parse(Console.ReadLine());
  433.         n = int.Parse(Console.ReadLine());
  434.         maxMove = c;
  435.         field = new int[n, n];
  436.         for (int row = 0; row < n; row++)
  437.         {
  438.             string rowText = Console.ReadLine();
  439.             string[] rowCells = rowText.Split(' ');
  440.             for (int col = 0; col < n; col++)
  441.             {
  442.                 field[row, col] = int.Parse(rowCells[col]);
  443.             }
  444.         }
  445.     }
  446.  
  447.  
  448.  
  449. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement