Slavik9510

Untitled

Apr 24th, 2023
107
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C# 23.48 KB | None | 0 0
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Drawing;
  4. using System.Linq;
  5. using System.Reflection.Metadata;
  6. using System.Text;
  7. using System.Threading.Tasks;
  8. using System.Xml.Linq;
  9.  
  10. namespace DO_Lab4
  11. {
  12.     public static class MyExtensions
  13.     {
  14.         public static void Fill<T>(this T[,] array, T value)
  15.         {
  16.             for (int i = 0; i < array.GetLength(0); i++)
  17.             {
  18.                 for (int j = 0; j < array.GetLength(1); j++)
  19.                 {
  20.                     array[i, j] = value;
  21.                 }
  22.             }
  23.         }
  24.         public static void Remove(this ref Direction value, Direction flags)
  25.         {
  26.             value = value & ~flags;
  27.         }
  28.         public static void Add(this ref Direction value, Direction flags)
  29.         {
  30.             value |= flags;
  31.         }
  32.         public static bool Contains(this Direction value, Direction flag)
  33.         {
  34.             return (value & flag) != Direction.None;
  35.         }
  36.  
  37.     }
  38.     [Flags]
  39.     public enum Direction
  40.     {
  41.         None = 0,
  42.         Left = 1,
  43.         Right = 2,
  44.         Up = 4,
  45.         Down = 8,
  46.         All = 16
  47.     }
  48.     class Vertex
  49.     {
  50.         public int Row;
  51.         public int Column;
  52.         public Direction AcceptableDirections;
  53.         public Vertex(int row, int column, Direction directions)
  54.         {
  55.             this.Row = row;
  56.             this.Column = column;
  57.             AcceptableDirections = directions;
  58.         }
  59.         public override bool Equals(object obj)
  60.         {
  61.             if (obj == null || GetType() != obj.GetType())
  62.             {
  63.                 return false;
  64.             }
  65.  
  66.             Vertex other = (Vertex)obj;
  67.             return (Row == other.Row && Column == other.Column);
  68.         }
  69.     }
  70.     struct Consumer
  71.     {
  72.         public int transportationCosts;
  73.         public int metNeeds;
  74.         public int sign;
  75.     }
  76.  
  77.     internal class PotencialMethod
  78.     {
  79.         const int FICTITIOUS_FILLING = int.MaxValue - 1;
  80.         int[] needs;
  81.         int[] stocks;
  82.         int[] u;
  83.         int[] v;
  84.         Consumer[,] consumers;
  85.  
  86.         //------------------------
  87.         private void printArr()
  88.         {
  89.             for (int i = 0; i < consumers.GetLength(0) + 1; i++)
  90.             {
  91.                 if (i < consumers.GetLength(0))
  92.                 {
  93.                     for (int j = 0; j < consumers.GetLength(1) + 1; j++)
  94.                     {
  95.                         if (j < consumers.GetLength(1))
  96.                         {
  97.                             Console.Write($"{consumers[i, j].transportationCosts} / {consumers[i, j].metNeeds,-4} ");
  98.                         }
  99.                         else
  100.                         {
  101.                             Console.WriteLine(stocks[i]);
  102.                         }
  103.                     }
  104.                 }
  105.                 else
  106.                 {
  107.                     for (int j = 0; j < needs.Length; j++)
  108.                     {
  109.                         Console.Write($"{needs[j],3} ");
  110.                     }
  111.                 }
  112.             }
  113.  
  114.             int sum = 0;
  115.             for (int i = 0; i < consumers.GetLength(0); i++)
  116.             {
  117.                 for (int j = 0; j < consumers.GetLength(1); j++)
  118.                 {
  119.                     sum += consumers[i, j].transportationCosts * consumers[i, j].metNeeds;
  120.                 }
  121.             }
  122.  
  123.             //Console.WriteLine("\nSUM  = " + sum);
  124.         }
  125.  
  126.         private void printSigns()
  127.         {
  128.             for (int i = 0; i < consumers.GetLength(0); i++)
  129.             {
  130.                 for (int j = 0; j < consumers.GetLength(1); j++)
  131.                 {
  132.                     Console.Write($"{consumers[i, j].sign,-3} ");
  133.                 }
  134.                 Console.WriteLine();
  135.             }
  136.         }
  137.         //------------------------
  138.         public PotencialMethod(string path)
  139.         {
  140.             string[] data = File.ReadAllLines(path);
  141.             stocks = new int[data.Length - 1];
  142.             u = new int[stocks.Length];
  143.             Array.Fill(u, int.MinValue);
  144.             needs = new int[data.Last().Split(' ').Length];
  145.             v = new int[needs.Length];
  146.             Array.Fill(v, int.MinValue);
  147.  
  148.             consumers = new Consumer[stocks.Length, needs.Length];
  149.  
  150.             for (int i = 0; i < consumers.GetLength(0); i++)
  151.             {
  152.                 for (int j = 0; j < consumers.GetLength(1); j++)
  153.                 {
  154.                     //consumers[i, j].metNeeds = 0;
  155.                 }
  156.             }
  157.  
  158.             for (int i = 0; i < data.Length; i++)
  159.             {
  160.                 string[] current = data[i].Split(' ');
  161.                 if (i < data.Length - 1)
  162.                 {
  163.                     for (int j = 0; j < current.Length; j++)
  164.                     {
  165.                         if (j < current.Length - 1)
  166.                         {
  167.                             consumers[i, j].transportationCosts = int.Parse(current[j]);
  168.                         }
  169.                         else
  170.                         {
  171.                             stocks[i] = int.Parse(current[j]);
  172.                         }
  173.                     }
  174.                 }
  175.                 else
  176.                 {
  177.                     for (int j = 0; j < current.Length; j++)
  178.                     {
  179.                         needs[j] = int.Parse(current[j]);
  180.                     }
  181.                 }
  182.             }
  183.  
  184.             // minimumElementMethod();
  185.             //printArr();
  186.         }
  187.  
  188.         private (int, int) findMin()
  189.         {
  190.             int min = int.MaxValue;
  191.             int iVal = -1, jVal = -1;
  192.  
  193.             for (int i = 0; i < consumers.GetLength(0); i++)
  194.             {
  195.                 if (stocks[i] == 0) continue;
  196.  
  197.                 for (int j = 0; j < consumers.GetLength(1); j++)
  198.                 {
  199.                     if (needs[j] != 0 && consumers[i, j].transportationCosts < min)
  200.                     {
  201.                         min = consumers[i, j].transportationCosts;
  202.                         iVal = i;
  203.                         jVal = j;
  204.                     }
  205.                 }
  206.             }
  207.             return (iVal, jVal);
  208.         }
  209.         private void minimumElementMethod()
  210.         {
  211.             bool isSolved = false;
  212.  
  213.             while (!isSolved)
  214.             {
  215.                 (int iVal, int jVal) = findMin();
  216.  
  217.                 int valueToTransport = Math.Min(stocks[iVal], needs[jVal]);
  218.                 consumers[iVal, jVal].metNeeds = valueToTransport;
  219.                 stocks[iVal] -= valueToTransport;
  220.                 needs[jVal] -= valueToTransport;
  221.  
  222.                 isSolved = true;
  223.                 for (int i = 0; i < needs.Length; i++)
  224.                 {
  225.                     if (needs[i] != 0)
  226.                     {
  227.                         isSolved = false;
  228.                         break;
  229.                     }
  230.                 }
  231.             }
  232.         }
  233.         private void northwestAngleMethod()
  234.         {
  235.             bool isSolved = false;
  236.  
  237.             int row = 0, column = 0;
  238.             while (!isSolved)
  239.             {
  240.  
  241.                 isSolved = true;
  242.                 for (int i = 0; i < needs.Length; i++)
  243.                 {
  244.                     if (needs[i] != 0)
  245.                     {
  246.                         isSolved = false;
  247.                         break;
  248.                     }
  249.                 }
  250.             }
  251.         }
  252.         private int findMostPopulatedRow()
  253.         {
  254.             int zeroPotencialRow = 0, max = 0;
  255.             for (int i = 0; i < consumers.GetLength(0); i++)
  256.             {
  257.                 int sum = 0;
  258.                 for (int j = 0; j < consumers.GetLength(1); j++)
  259.                 {
  260.                     if (consumers[i, j].metNeeds > 0)
  261.                     {
  262.                         sum++;
  263.                     }
  264.                 }
  265.                 if (i == 0)
  266.                 {
  267.                     max = sum;
  268.                 }
  269.                 if (i > 1 && sum > max)
  270.                 {
  271.                     zeroPotencialRow = i;
  272.                     max = sum;
  273.                 }
  274.             }
  275.             return zeroPotencialRow;
  276.         }
  277.         private void calcPotencials()
  278.         {
  279.             for (int i = 0; i < u.Length; i++)
  280.             {
  281.                 u[i] = int.MinValue;
  282.             }
  283.             for (int i = 0; i < v.Length; i++)
  284.             {
  285.                 v[i] = int.MinValue;
  286.             }
  287.             int zeroPotencialRow = findMostPopulatedRow();
  288.             u[zeroPotencialRow] = 0;
  289.             bool isSolved = false;
  290.             while (!isSolved)
  291.             {
  292.                 for (int i = 0; i < consumers.GetLength(0); i++)
  293.                 {
  294.                     for (int j = 0; j < consumers.GetLength(1); j++)
  295.                     {
  296.                         if (consumers[i, j].metNeeds == 0) continue;
  297.  
  298.                         if (v[j] == int.MinValue && u[i] != int.MinValue)
  299.                         {
  300.                             v[j] = consumers[i, j].transportationCosts - u[i];
  301.                         }
  302.                         else if (u[i] == int.MinValue && v[j] != int.MinValue)
  303.                         {
  304.                             u[i] = consumers[i, j].transportationCosts - v[j];
  305.                         }
  306.                     }
  307.                 }
  308.                 isSolved = true;
  309.                 for (int i = 0; i < u.Length; i++)
  310.                 {
  311.                     if (u[i] == int.MinValue)
  312.                     {
  313.                         isSolved = false;
  314.                         break;
  315.                     }
  316.                 }
  317.                 if (isSolved)
  318.                 {
  319.                     for (int i = 0; i < v.Length; i++)
  320.                     {
  321.                         if (v[i] == int.MinValue)
  322.                         {
  323.                             isSolved = false;
  324.                             break;
  325.                         }
  326.                     }
  327.                 }
  328.             }
  329.         }
  330.         private void calcDeltas()
  331.         {
  332.             for (int i = 0; i < consumers.GetLength(0); i++)
  333.             {
  334.                 for (int j = 0; j < consumers.GetLength(1); j++)
  335.                 {
  336.                     consumers[i, j].sign = u[i] + v[j] - consumers[i, j].transportationCosts;
  337.                 }
  338.             }
  339.         }
  340.         private bool findMaxDelta(out int row, out int column)
  341.         {
  342.             bool isSolved = true;
  343.             int maxDelta = -1;
  344.             row = -1; column = -1;
  345.             for (int i = 0; i < consumers.GetLength(0); i++)
  346.             {
  347.                 for (int j = 0; j < consumers.GetLength(1); j++)
  348.                 {
  349.                     if (consumers[i, j].sign > 0)
  350.                     {
  351.                         isSolved = false;
  352.                         if (maxDelta == -1)
  353.                         {
  354.                             maxDelta = consumers[i, j].sign;
  355.                             row = i;
  356.                             column = j;
  357.                         }
  358.                         else if (consumers[i, j].sign >= maxDelta)
  359.                         {
  360.                             maxDelta = consumers[i, j].sign;
  361.                             row = i;
  362.                             column = j;
  363.                         }
  364.                     }
  365.                 }
  366.             }
  367.             return isSolved;
  368.         }
  369.         private Direction calcDirections(int row, int column, Direction forbidden = Direction.None)
  370.         {
  371.             Direction acceptable = Direction.None;
  372.  
  373.             for (int i = 0; i < consumers.GetLength(0); i++)
  374.             {
  375.                 if (i == row) continue;
  376.                 if (consumers[i, column].metNeeds > 0)
  377.                 {
  378.                     if (i < row)
  379.                     {
  380.                         acceptable.Add(Direction.Up);
  381.                         i = row;
  382.                     }
  383.                     else
  384.                     {
  385.                         acceptable.Add(Direction.Down);
  386.                         break;
  387.                     }
  388.                 }
  389.             }
  390.  
  391.             for (int j = 0; j < consumers.GetLength(1); j++)
  392.             {
  393.                 if (j == column) continue;
  394.  
  395.                 if (consumers[row, j].metNeeds > 0)
  396.                 {
  397.                     if (j < column)
  398.                     {
  399.                         acceptable.Add(Direction.Left);
  400.                         j = column;
  401.                     }
  402.                     else
  403.                     {
  404.                         acceptable.Add(Direction.Right);
  405.                         break;
  406.                     }
  407.                 }
  408.             }
  409.             acceptable.Remove(forbidden);
  410.             return acceptable;
  411.         }
  412.         private Vertex findNextVertex(Vertex vertex)
  413.         {
  414.             if (vertex.AcceptableDirections == Direction.None)
  415.             {
  416.                 throw new Exception("Немає допустимих напрямків");
  417.             }
  418.             if (vertex.AcceptableDirections.Contains(Direction.Up))
  419.             {
  420.                 for (int i = vertex.Row - 1; i >= 0; i--)
  421.                 {
  422.                     if (consumers[i, vertex.Column].metNeeds > 0)
  423.                     {
  424.                         vertex.AcceptableDirections.Remove(Direction.Up);
  425.                         return new Vertex(i, vertex.Column, calcDirections(i, vertex.Column, forbidden: Direction.Down));
  426.                     }
  427.                 }
  428.             }
  429.             else if (vertex.AcceptableDirections.Contains(Direction.Down))
  430.             {
  431.                 for (int i = vertex.Row + 1; i <= consumers.GetLength(0); i++)
  432.                 {
  433.                     if (consumers[i, vertex.Column].metNeeds > 0)
  434.                     {
  435.                         vertex.AcceptableDirections.Remove(Direction.Down);
  436.                         return new Vertex(i, vertex.Column, calcDirections(i, vertex.Column, forbidden: Direction.Up));
  437.                     }
  438.                 }
  439.             }
  440.             else if (vertex.AcceptableDirections.Contains(Direction.Left))
  441.             {
  442.                 for (int j = vertex.Column - 1; j >= 0; j--)
  443.                 {
  444.                     if (consumers[vertex.Row, j].metNeeds > 0)
  445.                     {
  446.                         vertex.AcceptableDirections.Remove(Direction.Left);
  447.                         return new Vertex(vertex.Row, j, calcDirections(vertex.Row, j, forbidden: Direction.Right));
  448.                     }
  449.                 }
  450.             }
  451.             else //Right
  452.             {
  453.                 for (int j = vertex.Column + 1; j <= consumers.GetLength(1); j++)
  454.                 {
  455.                     if (consumers[vertex.Row, j].metNeeds > 0)
  456.                     {
  457.                         vertex.AcceptableDirections.Remove(Direction.Right);
  458.                         return new Vertex(vertex.Row, j, calcDirections(vertex.Row, j, forbidden: Direction.Left));
  459.                     }
  460.                 }
  461.             }
  462.             return new Vertex(-1, -1, Direction.None); //Щоб забрати warning
  463.         }
  464.         private void removeUnnecessaryVertices(List<Vertex> cycleVertices)
  465.         {
  466.             for (int i = 2; i < cycleVertices.Count; i++)
  467.             {
  468.                 bool rowsMatched = cycleVertices[i].Row == cycleVertices[i - 1].Row && cycleVertices[i - 1].Row == cycleVertices[i - 2].Row;
  469.                 bool columnsMatched = cycleVertices[i].Column == cycleVertices[i - 1].Column && cycleVertices[i - 1].Column == cycleVertices[i - 2].Column;
  470.                 if (rowsMatched || columnsMatched)
  471.                 {
  472.                     // Знайдено три однакових значення підряд
  473.                     // Видалення середнього елемента
  474.                     int indexToRemove = i - 1;
  475.                     cycleVertices.RemoveAt(indexToRemove);
  476.                     // Зменшення лічильника циклу, щоб продовжити перевірку
  477.                     //!!!!!!!!!!!!!!!!!!!
  478.                     //i = 2;
  479.                     i--;
  480.                 }
  481.             }
  482.             //останній може бути в одному рядку/стовпці з передостанній і першим
  483.             if (cycleVertices.Last().Row == cycleVertices.ElementAt(cycleVertices.Count - 2).Row && cycleVertices.Last().Row == cycleVertices.First().Row)
  484.             {
  485.                 cycleVertices.RemoveAt(cycleVertices.Count - 1);
  486.             }
  487.             else if (cycleVertices.Last().Column == cycleVertices.ElementAt(cycleVertices.Count - 2).Column && cycleVertices.Last().Column == cycleVertices.First().Column)
  488.             {
  489.                 cycleVertices.RemoveAt(cycleVertices.Count - 1);
  490.             }
  491.         }
  492.         private List<Vertex> buildCycle(int row, int column)
  493.         {
  494.             bool isSolved = false;
  495.             List<Vertex> cycleVertices = new List<Vertex>();
  496.             int oldVal = consumers[row, column].metNeeds;
  497.             consumers[row, column].metNeeds = int.MaxValue;
  498.             cycleVertices.Add(new Vertex(row, column, calcDirections(row, column)));
  499.  
  500.             while (!isSolved)
  501.             {
  502.                 while (cycleVertices.Last().AcceptableDirections == Direction.None)
  503.                 {
  504.                     cycleVertices.Remove(cycleVertices.Last());
  505.                     if (cycleVertices.Count == 0)
  506.                     {
  507.                         Console.WriteLine("ERORRRRRRRRR 1");
  508.                         Environment.Exit(1);
  509.                     }
  510.                 }
  511.                 Vertex possibleNext = findNextVertex(cycleVertices.Last());
  512.                 if (possibleNext.Equals(cycleVertices.First()))
  513.                 {
  514.                     isSolved = true;
  515.                     consumers[row, column].metNeeds = oldVal;
  516.                 }
  517.                 else if (possibleNext.AcceptableDirections != Direction.None)
  518.                 {
  519.                     cycleVertices.Add(possibleNext);
  520.                 }
  521.             }
  522.             removeUnnecessaryVertices(cycleVertices);
  523.             return cycleVertices;
  524.         }
  525.         private bool checkForDegeneracy()
  526.         {
  527.             int count = 0;
  528.             foreach (Consumer consumer in consumers)
  529.             {
  530.                 if (consumer.metNeeds != 0)
  531.                 {
  532.                     count++;
  533.                 }
  534.             }
  535.             return count != consumers.GetLength(0) + consumers.GetLength(1) - 1;
  536.         }
  537.         private void recalculateTransportation(List<Vertex> cycleVertices)
  538.         {
  539.             int min = -1;
  540.             for (int i = 1; i < cycleVertices.Count; i++)
  541.             {
  542.                 if (i % 2 == 0) continue;
  543.                 int currentRow = cycleVertices[i].Row;
  544.                 int currentColumn = cycleVertices[i].Column;
  545.                 if (i == 1)
  546.                 {
  547.                     min = consumers[currentRow, currentColumn].metNeeds;
  548.                 }
  549.                 else if (consumers[currentRow, currentColumn].metNeeds < min)
  550.                 {
  551.                     min = consumers[currentRow, currentColumn].metNeeds;
  552.                 }
  553.             }
  554.  
  555.             for (int i = 0; i < cycleVertices.Count; i++)
  556.             {
  557.                 int currentRow = cycleVertices[i].Row;
  558.                 int currentColumn = cycleVertices[i].Column;
  559.                 if (consumers[currentRow, currentColumn].metNeeds == FICTITIOUS_FILLING)
  560.                 {
  561.                     consumers[currentColumn, currentColumn].metNeeds = 0;
  562.                 }
  563.                 if (i % 2 == 0)
  564.                 {
  565.                     consumers[currentRow, currentColumn].metNeeds += min;
  566.                 }
  567.                 else
  568.                 {
  569.                     consumers[currentRow, currentColumn].metNeeds -= min;
  570.                 }
  571.             }
  572.         }
  573.         private (int, int) fillMin()
  574.         {
  575.             int row = -1, column = -1;
  576.             if (u[0] == int.MinValue)
  577.             {
  578.                 int min = -1;
  579.                 for (int i = 0; i < consumers.GetLength(0); i++)
  580.                 {
  581.                     for (int j = 0; j < consumers.GetLength(1); j++)
  582.                     {
  583.                         if (consumers[i, j].metNeeds != 0) continue;
  584.  
  585.                         if (min == -1 || consumers[i, j].transportationCosts < min)
  586.                         {
  587.                             min = consumers[i, j].transportationCosts;
  588.                             row = i;
  589.                             column = j;
  590.                         }
  591.                     }
  592.                 }
  593.             }
  594.             else
  595.             {
  596.                 int max = -1;
  597.                 for (int i = 0; i < consumers.GetLength(0); i++)
  598.                 {
  599.                     for (int j = 0; j < consumers.GetLength(1); j++)
  600.                     {
  601.                         if (consumers[i, j].metNeeds != 0) continue;
  602.  
  603.                         if (max == -1 || consumers[i, j].sign > max)
  604.                         {
  605.                             max = consumers[i, j].sign;
  606.                             row = i;
  607.                             column = j;
  608.                         }
  609.                     }
  610.                 }
  611.             }
  612.             consumers[row, column].metNeeds = FICTITIOUS_FILLING;
  613.             return (row, column);
  614.         }
  615.         private void fixMin(int row, int column)
  616.         {
  617.             if (row == -1 || column == -1) return;
  618.             consumers[row, column].metNeeds = 0;
  619.         }
  620.         public void Solve()
  621.         {
  622.             minimumElementMethod();
  623.             // printArr();
  624.             // bool t = checkForDegeneracy();
  625.             bool isSolved = false;
  626.             int iter = 0;
  627.             while (!isSolved)
  628.             {
  629.                 bool isDegenerated = checkForDegeneracy();
  630.                 int minRow = -1, minColumn = -1;
  631.                 if (isDegenerated)
  632.                 {
  633.                     /*
  634.                     Console.WriteLine("План виродженаий, можливо не кiнцевий розвязок");
  635.                     int currentSum = 0;
  636.                     for (int i = 0; i < consumers.GetLength(0); i++)
  637.                     {
  638.                         for (int j = 0; j < consumers.GetLength(1); j++)
  639.                         {
  640.                             currentSum += consumers[i, j].transportationCosts * consumers[i, j].metNeeds;
  641.                         }
  642.                     }
  643.                     Console.WriteLine($"SUM = {currentSum}");
  644.                     Environment.Exit(2);
  645.                     */
  646.                     (minRow, minColumn) = fillMin();
  647.                 }
  648.                 calcPotencials();
  649.                 calcDeltas();
  650.                 isSolved = findMaxDelta(out int row, out int column);
  651.                 if (isSolved)
  652.                 {
  653.                     fixMin(minRow, minColumn);
  654.                     break;
  655.                 }
  656.                 var cycleVertices = buildCycle(row, column);
  657.                 fixMin(minRow, minColumn);
  658.                 recalculateTransportation(cycleVertices);
  659.                 printArr();
  660.                 Console.WriteLine();
  661.                 Console.WriteLine();
  662.             }
  663.  
  664.             int sum = 0;
  665.             for (int i = 0; i < consumers.GetLength(0); i++)
  666.             {
  667.                 for (int j = 0; j < consumers.GetLength(1); j++)
  668.                 {
  669.                     sum += consumers[i, j].transportationCosts * consumers[i, j].metNeeds;
  670.                 }
  671.             }
  672.             Console.WriteLine($"SUM = {sum}");
  673.         }
  674.     }
  675. }
  676.  
Add Comment
Please, Sign In to add comment