結果
問題 | No.5007 Steiner Space Travel |
ユーザー | inani_waon |
提出日時 | 2022-07-30 15:51:21 |
言語 | C# (.NET 8.0.203) |
結果 |
AC
|
実行時間 | 989 ms / 1,000 ms |
コード長 | 7,436 bytes |
コンパイル時間 | 9,270 ms |
実行使用メモリ | 168,212 KB |
スコア | 6,829,913 |
最終ジャッジ日時 | 2022-07-30 15:52:03 |
合計ジャッジ時間 | 39,309 ms |
ジャッジサーバーID (参考情報) |
judge11 / judge14 |
純コード判定しない問題か言語 |
(要ログイン)
テストケース
テストケース表示入力 | 結果 | 実行時間 実行使用メモリ |
---|---|---|
testcase_00 | AC | 972 ms
29,964 KB |
testcase_01 | AC | 972 ms
29,880 KB |
testcase_02 | AC | 973 ms
29,604 KB |
testcase_03 | AC | 973 ms
30,040 KB |
testcase_04 | AC | 972 ms
29,860 KB |
testcase_05 | AC | 973 ms
29,812 KB |
testcase_06 | AC | 973 ms
30,072 KB |
testcase_07 | AC | 974 ms
29,796 KB |
testcase_08 | AC | 971 ms
29,984 KB |
testcase_09 | AC | 973 ms
29,932 KB |
testcase_10 | AC | 973 ms
29,608 KB |
testcase_11 | AC | 989 ms
29,792 KB |
testcase_12 | AC | 973 ms
29,968 KB |
testcase_13 | AC | 973 ms
31,940 KB |
testcase_14 | AC | 973 ms
29,952 KB |
testcase_15 | AC | 973 ms
30,192 KB |
testcase_16 | AC | 973 ms
29,956 KB |
testcase_17 | AC | 973 ms
31,868 KB |
testcase_18 | AC | 973 ms
31,764 KB |
testcase_19 | AC | 973 ms
32,116 KB |
testcase_20 | AC | 974 ms
30,060 KB |
testcase_21 | AC | 973 ms
29,900 KB |
testcase_22 | AC | 973 ms
32,020 KB |
testcase_23 | AC | 973 ms
31,700 KB |
testcase_24 | AC | 973 ms
31,968 KB |
testcase_25 | AC | 973 ms
31,844 KB |
testcase_26 | AC | 973 ms
31,760 KB |
testcase_27 | AC | 973 ms
29,872 KB |
testcase_28 | AC | 974 ms
30,060 KB |
testcase_29 | AC | 973 ms
168,212 KB |
コンパイルメッセージ
Determining projects to restore... Restored /home/judge/data/code/main.csproj (in 144 ms). .NET 向け Microsoft (R) Build Engine バージョン 17.0.0-preview-21470-01+cb055d28f Copyright (C) Microsoft Corporation.All rights reserved. プレビュー版の .NET を使用しています。https://aka.ms/dotnet-core-preview をご覧ください main -> /home/judge/data/code/bin/Release/net6.0/main.dll main -> /home/judge/data/code/bin/Release/net6.0/publish/
ソースコード
using System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Text; class Yukico5007 { static void Main(string[] args) { var sw = Stopwatch.StartNew(); var nums = Console.ReadLine().Split(' ').Select(int.Parse).ToArray(); var N = nums[0]; var M = nums[1]; var planets = new List<(int y, int x)>(); for (int i = 0; i < N; i++) { nums = Console.ReadLine().Split(' ').Select(int.Parse).ToArray(); planets.Add((nums[0], nums[1])); } var directCosts = new double[(N + 1) * (N + 1)]; for (int i = 0; i < N; i++) { for (int j = 0; j < N; j++) { if (i == j) continue; var cost = Math.Sqrt(Math.Abs(planets[i].y - planets[j].y) * Math.Abs(planets[i].y - planets[j].y) + Math.Abs(planets[i].x - planets[j].x) * Math.Abs(planets[i].x - planets[j].x)); directCosts[i * (N + 1) + j] = cost; } } for (int i = 0; i < N; i++) { directCosts[(N + 1) * N + i] = directCosts[0 * (N + 1) + i]; directCosts[(N + 1) * i + N] = directCosts[i * (N + 1) + 0]; } var inputs = new Inputs(sw, planets, directCosts, null); var solver = new Solver(); var command = solver.GetCommand(inputs); command.Print(); } } class Inputs { /// <summary>惑星の座標</summary> public List<(int y, int x)> Planets; /// <summary>他の惑星を経由せずに直接飛ぶコスト(αは考慮しない)</summary> public double[] DirectCosts; /// <summary>他の惑星を経由して飛ぶ最小コスト(αは考慮しない)</summary> public double[] RouteCosts; public Stopwatch Sw; public const int N = 100; public const int NP1 = 101; public const int M = 8; public const int A = 5; public const int AA = 25; public Inputs(Stopwatch sw, List<(int y, int x)> planets, double[] directCosts, double[] routeCosts) { Sw = sw; Planets = planets; DirectCosts = directCosts; RouteCosts = routeCosts; } } class Outputs { public List<(int y, int x)> Stations = new(); public List<(int t, int r)> Route = new(); public void Print() { foreach (var pos in Stations) { Console.WriteLine($"{pos.y} {pos.x}"); } Console.WriteLine(Route.Count); foreach (var via in Route) { Console.WriteLine($"{via.t} {via.r + 1}"); } } } class Solver { public Outputs GetCommand(Inputs inputs) { var defaultRoute = Enumerable.Range(0, Inputs.N).Append(0).ToArray(); var twoOpt = new TwoOpt(Inputs.NP1, inputs.DirectCosts, defaultRoute, new Random(1728), inputs.Sw); twoOpt.Exec(); var res = new Outputs(); foreach (var i in twoOpt.IdxByOrders) { res.Route.Add((1, i)); } AddStations(inputs, res); return res; } void AddStations(Inputs inputs, Outputs outputs) { while (outputs.Stations.Count < 8) { var maxCost = double.MinValue; var maxCostIndex = -1; // (i - 1) -> i for (int i = 1; i < outputs.Route.Count - 1; i++) { var p1 = outputs.Route[i - 1]; var p2 = outputs.Route[i]; var p3 = outputs.Route[i + 1]; if (p2.t == 2) continue; double cost1; if (p1.t == 1 && p2.t == 1) { cost1 = inputs.DirectCosts[p1.r * Inputs.NP1 + p2.r] * Inputs.AA; } else { var rate = (p1.t == 2 && p2.t == 2) ? 1 : Inputs.A; var bfPos = p1.t == 1 ? inputs.Planets[p1.r] : outputs.Stations[p1.r]; var afPos = p2.t == 1 ? inputs.Planets[p2.r] : outputs.Stations[p2.r]; cost1 = Math.Sqrt(Math.Abs(bfPos.y - afPos.y) * Math.Abs(bfPos.y - afPos.y) + Math.Abs(bfPos.x - afPos.x) * Math.Abs(bfPos.x - afPos.x)) * rate; } double cost2; if (p2.t == 1 && p3.t == 1) { cost2 = inputs.DirectCosts[p2.r * Inputs.NP1 + p3.r] * Inputs.AA; } else { var rate = (p2.t == 2 && p3.t == 2) ? 1 : Inputs.A; var bfPos = p2.t == 1 ? inputs.Planets[p2.r] : outputs.Stations[p2.r]; var afPos = p3.t == 1 ? inputs.Planets[p3.r] : outputs.Stations[p3.r]; cost2 = Math.Sqrt(Math.Abs(bfPos.y - afPos.y) * Math.Abs(bfPos.y - afPos.y) + Math.Abs(bfPos.x - afPos.x) * Math.Abs(bfPos.x - afPos.x)) * rate; } var cost = cost1 + cost2; if (cost > maxCost) { maxCostIndex = i; maxCost = cost; } } outputs.Stations.Add(inputs.Planets[outputs.Route[maxCostIndex].r]); outputs.Route.Insert(maxCostIndex, (2, outputs.Stations.Count - 1)); } } } public class TwoOpt { public readonly int NodeCount; public readonly int NodeCount2; public readonly double[] Costs; /// <summary>idx番目に経由する点がvalue番目の要素</summary> public readonly int[] IdxByOrders; Random _random; System.Diagnostics.Stopwatch _sw; public TwoOpt(int n, double[] costs, int[] defaultOrder, Random random, System.Diagnostics.Stopwatch sw) { NodeCount = n; NodeCount2 = defaultOrder.Length; Costs = costs; IdxByOrders = new int[NodeCount2]; Array.Copy(defaultOrder, IdxByOrders, NodeCount2); _random = random; _sw = sw; } public void Exec() { //var cnt = 0; var costsSpan = new Span<double>(Costs); while (_sw.ElapsedMilliseconds < 930) { for (int i = 0; i < 100; i++) { // 先頭、末尾は交換しない var from1order = _random.Next(NodeCount2 - 4); var from2order = _random.Next(from1order + 3, NodeCount2); var from1 = IdxByOrders[from1order]; var from2 = IdxByOrders[from2order]; var to1 = IdxByOrders[from1order + 1]; var to2 = IdxByOrders[from2order - 1]; // コスト計算 var oldRouteCost = costsSpan[from1 * NodeCount + to1] + costsSpan[from2 * NodeCount + to2]; var newRouteCost = costsSpan[from1 * NodeCount + to2] + costsSpan[from2 * NodeCount + to1]; // 改善されていれば更新 if (newRouteCost < oldRouteCost) Swap(from1order, from2order); } //cnt++; } } /// <summary> /// 2点の接続を交換する /// </summary> /// <param name="from1order">点1のOrder順</param> /// <param name="from2order">点2のOrder順</param> public void Swap(int from1order, int from2order) { Array.Reverse(IdxByOrders, from1order + 1, from2order - from1order - 1); } }