|
|
|
using System;
|
|
|
|
using System.Diagnostics;
|
|
|
|
using Combinatorics.Collections;
|
|
|
|
using System.Collections.Generic;
|
|
|
|
using static System.Console;
|
|
|
|
using System.Threading.Tasks;
|
|
|
|
|
|
|
|
namespace komvo
|
|
|
|
{
|
|
|
|
class Program
|
|
|
|
{
|
|
|
|
static void Main(string[] args)
|
|
|
|
{
|
|
|
|
Beginig:
|
|
|
|
|
|
|
|
List<Point> Points = new List<Point>();
|
|
|
|
Random random = new Random();
|
|
|
|
int pCount = 0;
|
|
|
|
Write("Введите количество точек: ");
|
|
|
|
|
|
|
|
Retry:
|
|
|
|
try
|
|
|
|
{
|
|
|
|
pCount = Convert.ToInt32(ReadLine());
|
|
|
|
}
|
|
|
|
catch
|
|
|
|
{
|
|
|
|
Write("Введите натуральное число: ");
|
|
|
|
goto Retry;
|
|
|
|
}
|
|
|
|
Stopwatch stopwatch = new Stopwatch();
|
|
|
|
stopwatch.Start();
|
|
|
|
|
|
|
|
for(int i = 0; i < pCount; i++)
|
|
|
|
{
|
|
|
|
int x = random.Next(80);
|
|
|
|
int y = random.Next(70);
|
|
|
|
Points.Add(new Point { X = x, Y = y });
|
|
|
|
WriteLine("Точка {0} [{1};{2}]", i + 1, x, y);
|
|
|
|
}
|
|
|
|
WriteLine("\n");
|
|
|
|
|
|
|
|
int matr = Points.Count;
|
|
|
|
double[,] Matrix = new double[matr, matr];
|
|
|
|
|
|
|
|
for (int i = 0; i < Points.Count; i++)
|
|
|
|
for (int j = i; j < Points.Count - 1; j++)
|
|
|
|
Matrix[i, j + 1] = Matrix[j + 1, i] =
|
|
|
|
Math.Sqrt(Math.Pow(Points[j + 1].X - Points[i].X, 2) + Math.Pow(Points[j + 1].Y - Points[i].Y, 2));
|
|
|
|
|
|
|
|
|
|
|
|
for (int i = 0; i < matr; i++)
|
|
|
|
{
|
|
|
|
for (int j = 0; j < matr; j++) Write("{0:00.00} ", Matrix[i, j]);
|
|
|
|
WriteLine();
|
|
|
|
}
|
|
|
|
int[] toSwap = new int[Points.Count - 1];
|
|
|
|
for (int i = 0; i <= toSwap.Length - 1; i++) toSwap[i] = i + 2;
|
|
|
|
|
|
|
|
bool first = true;
|
|
|
|
double opLength = 0, prevResult = 0;
|
|
|
|
string opRoute = string.Empty;
|
|
|
|
|
|
|
|
Permutations<int> perm = new Permutations<int>(toSwap);
|
|
|
|
foreach(IList<int> p in perm)
|
|
|
|
{
|
|
|
|
int[] route = new int[Points.Count - 1];
|
|
|
|
for (int i = 0; i < toSwap.Length; i++) route[i] = p[i];
|
|
|
|
prevResult = CountLength(Matrix, route);
|
|
|
|
//WriteLine(opLength);
|
|
|
|
|
|
|
|
if (first)
|
|
|
|
{
|
|
|
|
opLength = prevResult;
|
|
|
|
first = false;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(opLength > prevResult)
|
|
|
|
{
|
|
|
|
opLength = prevResult;
|
|
|
|
opRoute = string.Empty;
|
|
|
|
foreach (int i in route) opRoute += i + ";";
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//int[] toSwapNew = new int[Points.Count - 1];
|
|
|
|
//for (int i = 0; i <= toSwap.Length - 1; i++) toSwapNew[i] = i + 2;
|
|
|
|
//foreach (int i in toSwapNew) Write(i + " ");
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
WriteLine("\n\n1;{1}1 - оптимальный маршрут длинной {0:00.00}\nИз {2} маршрутов при {3} точках\nПосчитано за {4} мс\n\n",
|
|
|
|
opLength, opRoute, Fact(Points.Count-1), Points.Count, stopwatch.ElapsedMilliseconds);
|
|
|
|
stopwatch.Stop();
|
|
|
|
|
|
|
|
Write("Ещё раз? (y/n)");
|
|
|
|
char answer = ReadKey().KeyChar;
|
|
|
|
if (answer == 'y')
|
|
|
|
{
|
|
|
|
Points.Clear();
|
|
|
|
WriteLine("\n");
|
|
|
|
goto Beginig;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
public static double CountLength(double[,] mtr, int[] route)
|
|
|
|
{
|
|
|
|
double result = 0;
|
|
|
|
|
|
|
|
for (int j = 0; j < route.Length - 1; j++)
|
|
|
|
{
|
|
|
|
if (j == 0) result += mtr[0, route[j] - 1];
|
|
|
|
else if (j == route.Length - 1)
|
|
|
|
{
|
|
|
|
result += mtr[route[j - 1] - 2, route[j] - 2];
|
|
|
|
result += mtr[0, route[j] - 2];
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
result += mtr[route[j - 1] - 2, route[j] - 2];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
public partial struct Point
|
|
|
|
{
|
|
|
|
public int X { get; set; }
|
|
|
|
public int Y { get; set; }
|
|
|
|
}
|
|
|
|
|
|
|
|
static int Fact(int a) => a <= 1 ? 1 : a * Fact(a - 1);
|
|
|
|
}
|
|
|
|
}
|