結果
問題 | No.5017 Tool-assisted Shooting |
ユーザー | inani_waon |
提出日時 | 2023-07-16 18:47:47 |
言語 | C# (.NET 8.0.203) |
結果 |
AC
|
実行時間 | 157 ms / 2,000 ms |
コード長 | 8,195 bytes |
コンパイル時間 | 7,579 ms |
コンパイル使用メモリ | 141,740 KB |
実行使用メモリ | 48,108 KB |
スコア | 4,186,490 |
平均クエリ数 | 991.16 |
最終ジャッジ日時 | 2023-07-16 18:49:05 |
合計ジャッジ時間 | 25,684 ms |
ジャッジサーバーID (参考情報) |
judge12 / judge15 |
純コード判定しない問題か言語 |
(要ログイン)
テストケース
テストケース表示入力 | 結果 | 実行時間 実行使用メモリ |
---|---|---|
testcase_00 | AC | 127 ms
47,968 KB |
testcase_01 | AC | 126 ms
46,180 KB |
testcase_02 | AC | 133 ms
45,688 KB |
testcase_03 | AC | 126 ms
45,136 KB |
testcase_04 | AC | 134 ms
47,216 KB |
testcase_05 | AC | 126 ms
45,456 KB |
testcase_06 | AC | 156 ms
47,812 KB |
testcase_07 | AC | 125 ms
45,708 KB |
testcase_08 | AC | 126 ms
45,216 KB |
testcase_09 | AC | 127 ms
47,268 KB |
testcase_10 | AC | 126 ms
45,448 KB |
testcase_11 | AC | 125 ms
45,404 KB |
testcase_12 | AC | 89 ms
46,908 KB |
testcase_13 | AC | 126 ms
47,428 KB |
testcase_14 | AC | 149 ms
45,288 KB |
testcase_15 | AC | 123 ms
45,568 KB |
testcase_16 | AC | 124 ms
45,876 KB |
testcase_17 | AC | 125 ms
45,864 KB |
testcase_18 | AC | 125 ms
47,852 KB |
testcase_19 | AC | 125 ms
45,924 KB |
testcase_20 | AC | 126 ms
45,532 KB |
testcase_21 | AC | 155 ms
45,532 KB |
testcase_22 | AC | 126 ms
45,508 KB |
testcase_23 | AC | 124 ms
46,160 KB |
testcase_24 | AC | 125 ms
45,752 KB |
testcase_25 | AC | 127 ms
48,024 KB |
testcase_26 | AC | 127 ms
45,536 KB |
testcase_27 | AC | 126 ms
47,904 KB |
testcase_28 | AC | 126 ms
46,156 KB |
testcase_29 | AC | 125 ms
45,828 KB |
testcase_30 | AC | 124 ms
45,572 KB |
testcase_31 | AC | 126 ms
47,740 KB |
testcase_32 | AC | 127 ms
47,640 KB |
testcase_33 | AC | 128 ms
48,108 KB |
testcase_34 | AC | 125 ms
45,368 KB |
testcase_35 | AC | 128 ms
47,988 KB |
testcase_36 | AC | 157 ms
45,616 KB |
testcase_37 | AC | 127 ms
47,804 KB |
testcase_38 | AC | 127 ms
47,172 KB |
testcase_39 | AC | 126 ms
45,608 KB |
testcase_40 | AC | 126 ms
45,860 KB |
testcase_41 | AC | 125 ms
45,932 KB |
testcase_42 | AC | 126 ms
46,236 KB |
testcase_43 | AC | 151 ms
45,224 KB |
testcase_44 | AC | 126 ms
45,520 KB |
testcase_45 | AC | 128 ms
45,608 KB |
testcase_46 | AC | 124 ms
45,852 KB |
testcase_47 | AC | 124 ms
45,132 KB |
testcase_48 | AC | 126 ms
45,488 KB |
testcase_49 | AC | 125 ms
47,520 KB |
testcase_50 | AC | 124 ms
45,272 KB |
testcase_51 | AC | 125 ms
46,012 KB |
testcase_52 | AC | 127 ms
47,820 KB |
testcase_53 | AC | 126 ms
47,508 KB |
testcase_54 | AC | 134 ms
46,152 KB |
testcase_55 | AC | 127 ms
45,576 KB |
testcase_56 | AC | 143 ms
45,516 KB |
testcase_57 | AC | 142 ms
47,612 KB |
testcase_58 | AC | 152 ms
46,360 KB |
testcase_59 | AC | 143 ms
47,980 KB |
testcase_60 | AC | 142 ms
47,328 KB |
testcase_61 | AC | 128 ms
45,536 KB |
testcase_62 | AC | 125 ms
45,908 KB |
testcase_63 | AC | 126 ms
46,040 KB |
testcase_64 | AC | 124 ms
47,648 KB |
testcase_65 | AC | 144 ms
47,456 KB |
testcase_66 | AC | 128 ms
45,696 KB |
testcase_67 | AC | 124 ms
45,392 KB |
testcase_68 | AC | 137 ms
45,360 KB |
testcase_69 | AC | 140 ms
47,392 KB |
testcase_70 | AC | 141 ms
45,488 KB |
testcase_71 | AC | 141 ms
46,356 KB |
testcase_72 | AC | 148 ms
45,264 KB |
testcase_73 | AC | 125 ms
45,448 KB |
testcase_74 | AC | 124 ms
45,812 KB |
testcase_75 | AC | 125 ms
45,092 KB |
testcase_76 | AC | 125 ms
45,668 KB |
testcase_77 | AC | 126 ms
46,020 KB |
testcase_78 | AC | 131 ms
45,912 KB |
testcase_79 | AC | 136 ms
45,216 KB |
testcase_80 | AC | 137 ms
45,116 KB |
testcase_81 | AC | 141 ms
45,696 KB |
testcase_82 | AC | 139 ms
47,404 KB |
testcase_83 | AC | 131 ms
45,900 KB |
testcase_84 | AC | 125 ms
46,208 KB |
testcase_85 | AC | 127 ms
47,884 KB |
testcase_86 | AC | 138 ms
45,280 KB |
testcase_87 | AC | 125 ms
45,516 KB |
testcase_88 | AC | 127 ms
46,328 KB |
testcase_89 | AC | 127 ms
45,852 KB |
testcase_90 | AC | 126 ms
45,356 KB |
testcase_91 | AC | 127 ms
45,780 KB |
testcase_92 | AC | 126 ms
46,088 KB |
testcase_93 | AC | 132 ms
45,744 KB |
testcase_94 | AC | 124 ms
45,176 KB |
testcase_95 | AC | 125 ms
45,832 KB |
testcase_96 | AC | 125 ms
45,520 KB |
testcase_97 | AC | 127 ms
47,300 KB |
testcase_98 | AC | 125 ms
45,848 KB |
testcase_99 | AC | 126 ms
45,668 KB |
コンパイルメッセージ
Determining projects to restore... Restored /home/judge/data/code/main.csproj (in 124 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 をご覧ください /home/judge/data/code/Main.cs(177,17): warning CS8632: '#nullable' 注釈コンテキスト内のコードでのみ、Null 許容参照型の注釈を使用する必要があります。 [/home/judge/data/code/main.csproj] 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.Linq; public class YukicoScore6 { public static void Main(string[] args) { #if DEBUG // 入力ファイルを流し込んで使うときにフォーマット差を吸収する Console.ReadLine(); #endif var solver = new Solver(); for (int turn = 0; turn < 1000; turn++) { var n = int.Parse(Console.ReadLine()); if (n == -1) return; for (int j = 0; j < n; j++) { var nums = Console.ReadLine().Split(' ').Select(int.Parse).ToArray(); var enemy = new Enemy(nums[0], nums[1], turn); solver.AddEnemy( nums[2], enemy); } var cmd = solver.GetCommand(); Console.WriteLine(cmd); Console.Out.Flush(); solver.ExecCommand(cmd); } } } public class Solver { Random Random = new Random(1728); State State = new State(); public string GetCommand() { var bestScore = int.MinValue; var bestX = State.PlayerX; var bestCmd = "S"; for (int x = 0; x < Inputs.Width; x++) { var enemy = State.GetFirstEnemy(x); if (enemy == null) continue; var attackTurn = (int)Math.Ceiling(enemy.HP / (double)(State.PlayerLevel)); // todo 衝突を回避する前提でターンを考える var moveTurn1 = Math.Abs(x - State.PlayerX); // ループしない var moveTurn2 = Math.Abs(0 - State.PlayerX) + Math.Abs(Inputs.Width - x); // 左側へループ var moveTurn3 = Math.Abs(Inputs.Width - State.PlayerX) + Math.Abs(0 - x); // 右側へループ var bestMoveTurn = Math.Min(Math.Min(moveTurn1, moveTurn2), moveTurn3); if (bestMoveTurn > 0) bestMoveTurn--; if (State.Turn + attackTurn + bestMoveTurn >= GetEnemyCollisionTurn(enemy)) continue; // 倒すのが間に合わない(衝突) if (State.Turn + attackTurn + bestMoveTurn > 1000) continue; // 倒すのが間に合わない(時間切れ) var score = (State.PlayerLevel < 180 ? enemy.Power : enemy.InitHP) * 10000 / (attackTurn + bestMoveTurn); if (State.Turn >= 100) score = score * (100 + (State.Turn - enemy.AppearanceTurn)); if (State.PlayerLevel < 5) score += ((State.PlayerPower + enemy.Power) / 100) * 10000; if (score > bestScore) { bestScore = score; bestX = x; if (moveTurn1 <= moveTurn2 && moveTurn1 <= moveTurn3) { bestCmd = x == State.PlayerX ? "S" : (x < State.PlayerX ? "L" : "R"); } else if (moveTurn2 <= moveTurn1 && moveTurn2 <= moveTurn3) { bestCmd = "L"; } else { bestCmd = "R"; } } } // 無理矢理に衝突を回避する // 敵→自機で動くので、自分が動いた後と次ターンの敵が動くときに衝突の可能性がある // 1ターンで倒せるなら次ターンの衝突は無い // (今ターンで衝突する場合は時すでに手遅れ) if (bestCmd == "L") { var nextX = (State.PlayerX + Inputs.Width - 1) % Inputs.Width; var enemy = State.GetFirstEnemy(nextX); var colTurn = enemy == null ? -1 : GetEnemyCollisionTurn(enemy); var exCol = enemy == null ? 0 : (enemy.HP > State.PlayerLevel ? 1 : 0); if (enemy != null && (colTurn == State.Turn || colTurn == State.Turn + exCol)) bestCmd = "S"; } if (bestCmd == "R") { var nextX = (State.PlayerX + 1) % Inputs.Width; var enemy = State.GetFirstEnemy(nextX); var colTurn = enemy == null ? -1 : GetEnemyCollisionTurn(enemy); var exCol = enemy == null ? 0 : (enemy.HP > State.PlayerLevel ? 1 : 0); if (enemy != null && (colTurn == State.Turn || colTurn == State.Turn + exCol)) bestCmd = "S"; } if (bestCmd == "S") { var nextX = State.PlayerX; var enemy = State.GetFirstEnemy(nextX); var colTurn = enemy == null ? -1 : GetEnemyCollisionTurn(enemy); var exCol = enemy == null ? 0 : (enemy.HP > State.PlayerLevel ? 1 : 0); if (enemy != null && (colTurn == State.Turn || colTurn == State.Turn + exCol)) { // todo 2体連続している場合はバグる。時間と気力が効果に見合えば直す var rightX = (State.PlayerX + 1) % Inputs.Width; var rightEnemy = State.GetFirstEnemy(rightX); var colTurnR = rightEnemy == null ? -1 : GetEnemyCollisionTurn(rightEnemy); var exColR = rightEnemy == null ? 0 : (rightEnemy.HP > State.PlayerLevel ? 1 : 0); if (rightEnemy == null || (colTurnR != State.Turn && colTurnR != State.Turn + exColR)) bestCmd = "R"; var leftX = (State.PlayerX + Inputs.Width - 1) % Inputs.Width; var leftEnemy = State.GetFirstEnemy(leftX); var colTurnL = leftEnemy == null ? -1 : GetEnemyCollisionTurn(leftEnemy); var exColL = leftEnemy == null ? 0 : (leftEnemy.HP > State.PlayerLevel ? 1 : 0); if (leftEnemy == null || (colTurnL != State.Turn && colTurnL != State.Turn + exColL)) bestCmd = "L"; } } return bestCmd; } public void ExecCommand(string cmd) { State.Turn++; State.RemoveOldEnemy(); if (cmd == "L") State.PlayerX = (State.PlayerX + Inputs.Width - 1) % Inputs.Width; if (cmd == "R") State.PlayerX = (State.PlayerX + 1) % Inputs.Width; var enemy = State.GetFirstEnemy(State.PlayerX); if (enemy == null) return; enemy.HP -= State.PlayerLevel; if (enemy.HP > 0) return; State.RemoveFirstEnemy(State.PlayerX); State.PlayerPower += enemy.Power; State.PlayerLevel = 1 + State.PlayerPower / 100; } public void AddEnemy(int x, Enemy enemy) { State.AddEnemy(x, enemy); } /// <summary>敵と自機が衝突するターンを取得する(敵が最下段に移動するターン)</summary> private int GetEnemyCollisionTurn(Enemy enemy) { return enemy.AppearanceTurn + Inputs.Height - 1; } } public class State { public int Turn { get; set; } /// <summary>列ごとの敵リスト</summary> public List<Enemy>[] Columns = new List<Enemy>[Inputs.Width]; public int PlayerX { get; set; } = 12; public int PlayerPower { get; set; } = 0; public int PlayerLevel { get; set; } = 1; public State() { for (int i = 0; i < Inputs.Width; i++) { Columns[i] = new List<Enemy>(); } } public void AddEnemy(int x, Enemy enemy) { Columns[x].Add(enemy); } public Enemy? GetFirstEnemy(int x) { if (!Columns[x].Any()) return null; return Columns[x][0]; } public void RemoveOldEnemy() { for (int x = 0; x < Inputs.Width; x++) { if (!Columns[x].Any()) continue; var bottomEnemy = Columns[x][0]; if (bottomEnemy.AppearanceTurn + Inputs.Height <= Turn) { Columns[x].RemoveAt(0); } } } public void RemoveFirstEnemy(int x) { Columns[x].RemoveAt(0); } } public class Inputs { public const int Width = 25; public const int Height = 60; } public class Enemy { public int InitHP { get; } public int HP { get; set; } public int Power { get; } /// <summary>出現ターン</summary> public int AppearanceTurn { get; } public Enemy(int initHP, int power, int appearanceTurn) { InitHP = initHP; HP = initHP; Power = power; AppearanceTurn = appearanceTurn; } }