static void TestOffline() { int S = int.Parse(Console.ReadLine()); int C = int.Parse(Console.ReadLine()); int[] cities = new int[C]; for (int i = 0; i < C; ++i) { cities[i] = int.Parse(Console.ReadLine()); } double junctionCost = double.Parse(Console.ReadLine()); double failureProbability = double.Parse(Console.ReadLine()); RoadsAndJunctions rj = new RoadsAndJunctions(); int[] ret = rj.buildJunctions(S, cities, junctionCost, failureProbability); Console.WriteLine(ret.Length); for (int i = 0; i < ret.Length; ++i) { Console.WriteLine(ret[i]); } Console.Out.Flush(); int J = int.Parse(Console.ReadLine()); int[] junctionStatus = new int[J]; for (int i = 0; i < J; ++i) { junctionStatus[i] = int.Parse(Console.ReadLine()); } ret = rj.buildRoads(junctionStatus); Console.WriteLine(ret.Length); for (int i = 0; i < ret.Length; ++i) { Console.WriteLine(ret[i]); } }
private static double RunTest(string testFile, out TimeSpan testTime, string imageFile, out double junctionCost, out double failureProbability) { // Parse test int mapSize; City[] cities; bool[] junctionStatus; ParseTest(testFile, out mapSize, out cities, out junctionCost, out failureProbability, out junctionStatus); // Solve test Junction[] junctions; RoadsAndJunctions solver = new RoadsAndJunctions(); int[] citiesArray = new int[cities.Length * 2]; for (int i = 0; i < cities.Length; i++) { citiesArray[2 * i] = cities[i].X; citiesArray[2 * i + 1] = cities[i].Y; } Stopwatch sw = Stopwatch.StartNew(); int[] junctionsArray = solver.buildJunctions(mapSize, citiesArray, junctionCost, failureProbability); sw.Stop(); if (junctionsArray.Length % 2 == 1) { throw new Exception($"Invalid junctions array size ({junctionsArray.Length}) - it has odd number of elements"); } junctions = new Junction[junctionsArray.Length / 2]; for (int i = 0; i < junctionsArray.Length / 2; i++) { junctions[i] = new Junction() { X = junctionsArray[2 * i], Y = junctionsArray[2 * i + 1], }; } // Verify junctions if (junctions.Length > cities.Length * 2) { throw new Exception($"Too many junctions"); } foreach (Junction junction in junctions) { if (junction.X < 0 || junction.X >= mapSize || junction.Y < 0 || junction.Y >= mapSize) { throw new Exception($"Junction coordinates are incorrect: {junction}"); } if (cities.Any(c => c.X == junction.X && c.Y == junction.Y)) { throw new Exception($"Junction cannot be built in a city: {junction}"); } } // Build roads sw.Start(); int[] roadsArray = solver.buildRoads(junctionStatus.Take(junctions.Length).Select(j => j ? 1 : 0).ToArray()); sw.Stop(); testTime = sw.Elapsed; // Verify that roads are correct if (roadsArray.Length % 2 == 1) { throw new Exception($"Invalid roads array size ({roadsArray.Length}) - it has odd number of elements"); } for (int i = 0; i < roadsArray.Length; i++) { if (roadsArray[i] < 0 || roadsArray[i] >= cities.Length + junctions.Length) { throw new Exception($"Invalid road index: {roadsArray[i]}"); } if (roadsArray[i] >= cities.Length && !junctionStatus[roadsArray[i] - cities.Length]) { throw new Exception($"You can not build a road to a dysfunctional junction: {roadsArray[i] - cities.Length}"); } } // Convert roads Tuple <int, int>[] roads = new Tuple <int, int> [roadsArray.Length / 2]; for (int i = 0; i < roads.Length; i++) { roads[i] = Tuple.Create(roadsArray[2 * i], roadsArray[2 * i + 1]); } Tuple <City, City>[] roadsCities = new Tuple <City, City> [roads.Length]; for (int i = 0; i < roads.Length; i++) { int i1 = roads[i].Item1; int i2 = roads[i].Item2; City first, second; if (i1 < cities.Length) { first = cities[i1]; } else { first = new City() { X = junctions[i1 - cities.Length].X, Y = junctions[i1 - cities.Length].Y, } }; if (i2 < cities.Length) { second = cities[i2]; } else { second = new City() { X = junctions[i2 - cities.Length].X, Y = junctions[i2 - cities.Length].Y, } }; roadsCities[i] = Tuple.Create(first, second); } // TODO: Verify that all cities are connected // Draw image if (!string.IsNullOrEmpty(imageFile)) { const int scale = 5; float zoom = Math.Max(1, mapSize / 200.0f); float roadPenWidth = 1.5f * zoom; float cityRadius = scale * zoom; float junctionRadius = scale * zoom; float xOffset = scale / 2.0f; float yOffset = scale / 2.0f; Pen roadPen = new Pen(Color.Black, roadPenWidth); using (Bitmap bmp = new Bitmap(mapSize * scale, mapSize * scale)) { using (Graphics g = Graphics.FromImage(bmp)) { g.CompositingQuality = System.Drawing.Drawing2D.CompositingQuality.HighQuality; g.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic; g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality; g.FillRectangle(Brushes.White, 0, 0, bmp.Width, bmp.Height); // Draw roads foreach (var road in roadsCities) { City first = road.Item1; City second = road.Item2; float x1 = first.X * scale + xOffset; float y1 = first.Y * scale + yOffset; float x2 = second.X * scale + xOffset; float y2 = second.Y * scale + yOffset; g.DrawLine(roadPen, x1, y1, x2, y2); } // Draw junctions for (int i = 0; i < junctions.Length; i++) { var junction = junctions[i]; float x = junction.X * scale + xOffset; float y = junction.Y * scale + yOffset; g.FillEllipse(junctionStatus[i] ? Brushes.Green : Brushes.Red, x - junctionRadius / 2, y - junctionRadius / 2, junctionRadius, junctionRadius); } // Draw cities foreach (var city in cities) { float x = city.X * scale + xOffset; float y = city.Y * scale + yOffset; g.FillEllipse(Brushes.Blue, x - cityRadius / 2, y - cityRadius / 2, cityRadius, cityRadius); } } Directory.CreateDirectory(Path.GetDirectoryName(imageFile)); bmp.Save(imageFile); } } // Calculate cost double cost = junctionCost * junctions.Length; for (int i = 0; i < roads.Length; i++) { cost += roadsCities[i].Item1.Distance(roadsCities[i].Item2); } return(cost); }