Advertisement
ArXen42

Поиск цепочки возрастания, вариант на списках

Mar 29th, 2016
477
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C# 4.10 KB | None | 0 0
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Diagnostics;
  4. using System.Linq;
  5.  
  6. /// <summary>
  7. /// Пара индексов для двумерного Int32 массива.
  8. /// </summary>
  9. public struct XY
  10. {
  11.     public XY(int x, int y)
  12.     {
  13.         this.x = x;
  14.         this.y = y;
  15.     }
  16.  
  17.     public int x, y;
  18.  
  19.     public int GetValue(int[,] arr)
  20.     {
  21.         return arr[x, y];
  22.     }
  23.  
  24.     public override string ToString()
  25.     {
  26.         return x.ToString() + ", " + y.ToString();
  27.     }
  28. }
  29.  
  30. public class Program
  31. {
  32.     public static void Main(String[] args)
  33.     {
  34.         int size1 = 4000, size2 = 4000;
  35.         int[,] arr = new int[size1,size2];
  36.  
  37.         Random random = new Random();
  38.         for (int x = 0; x < size1; x++)
  39.             for (int y = 0; y < size2; y++)
  40.                 arr[x, y] = random.Next();
  41.  
  42.         var timer = new Stopwatch();
  43.         timer.Start();
  44.         Console.WriteLine("Длина пути: " + GetLongestPathInArray(arr).Count);
  45.         timer.Stop();
  46.         Console.WriteLine("Память: " + (Process.GetCurrentProcess().WorkingSet64 / (1024 * 1024)).ToString() + " MB");
  47.         Console.WriteLine("Временя: " + timer.ElapsedMilliseconds);
  48.  
  49.         //GetLongestPathInArray(arr).ForEach(x => Console.WriteLine(x.GetValue(arr)));
  50.     }
  51.  
  52.     /// <summary>
  53.     /// Возвращает список элементов, обарзующих наиболее длинную цепочку возрастания в данном массиве.
  54.     /// </summary>
  55.     public static List<XY> GetLongestPathInArray(int[,] arr)
  56.     {
  57.         List<XY> longestPath = new List<XY>();
  58.         List<XY>[,] foundWays = new List<XY>[arr.GetLength(0),arr.GetLength(1)]; //Инициализируем вспомогательный массив уже найденных цепочек
  59.  
  60.         for (int x = 0; x < arr.GetLength(0); x++)
  61.             for (int y = 0; y < arr.GetLength(1);y++)
  62.             {
  63.                 List<XY> path = GetLongestPathFrom(arr, new XY(x, y), foundWays);
  64.  
  65.                 if (path.Count > longestPath.Count)
  66.                     longestPath = path;
  67.             }
  68.  
  69.         return longestPath;
  70.     }
  71.  
  72.     /// <summary>
  73.     /// Возвращает цепочку возрастания наибольшей длины от указанного элемента, включая его самого.
  74.     /// </summary>
  75.     private static List<XY> GetLongestPathFrom(int[,] arr, XY pos, List<XY>[,] foundWays)
  76.     {
  77.         if (foundWays[pos.x, pos.y] == null) //Если мы еще не искали цепочку для этого элемента
  78.         {
  79.             List<XY> neighbours = GetNeighbours(arr, pos).FindAll(n => n.GetValue(arr) > pos.GetValue(arr)); //Получаем возможные направления поиска
  80.             List<XY> longestPath = new List<XY>();
  81.  
  82.             foreach (XY neighbour in neighbours)
  83.             {
  84.                 List<XY> tmpPath = GetLongestPathFrom(arr, neighbour, foundWays); //Ищем наиболее "перспективного" соседа
  85.  
  86.                 if (tmpPath.Count > longestPath.Count)
  87.                     longestPath = tmpPath;
  88.             }
  89.  
  90.             longestPath = new List<XY>(longestPath); //Необходимо клонировать, т.к. иначе будет изменяться сохраненный путь у соседа.
  91.             longestPath.Insert(0, pos); //Добавляем себя к пути соседа и сохраняем
  92.             foundWays[pos.x, pos.y] = longestPath;
  93.             return longestPath;
  94.         }
  95.         else
  96.             return foundWays[pos.x, pos.y];
  97.         //Такое "кэширование" позволяет ускорить алгоритм в несколько раз, избегая повторных рассчетов одинаковых цепочек.
  98.     }
  99.  
  100.     /// <summary>
  101.     /// Возвращает всех соседей указанного элемента (от 2 до 4, в зависимости от индексов).
  102.     /// </summary>
  103.     private static List<XY> GetNeighbours(int[,] arr, XY indexes)
  104.     {
  105.         List<XY> result = new List<XY>(2);
  106.  
  107.         if (indexes.x > 0)
  108.             result.Add(new XY(indexes.x - 1, indexes.y));
  109.         if (indexes.x < arr.GetLength(0) - 1)
  110.             result.Add(new XY(indexes.x + 1, indexes.y));
  111.  
  112.         if (indexes.y > 0)
  113.             result.Add(new XY(indexes.x, indexes.y - 1));
  114.         if (indexes.y < arr.GetLength(1) - 1)
  115.             result.Add(new XY(indexes.x, indexes.y + 1));
  116.  
  117.         return result;
  118.     }
  119. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement