예제 #1
0
    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]);
        }
    }
예제 #2
0
    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);
    }