結果
| 問題 |
No.5017 Tool-assisted Shooting
|
| ユーザー |
inani_waon
|
| 提出日時 | 2023-07-16 15:50:38 |
| 言語 | C# (.NET 8.0.404) |
| 結果 |
AC
|
| 実行時間 | 115 ms / 2,000 ms |
| コード長 | 5,235 bytes |
| コンパイル時間 | 7,199 ms |
| コンパイル使用メモリ | 145,280 KB |
| 実行使用メモリ | 47,444 KB |
| スコア | 392,687 |
| 平均クエリ数 | 359.02 |
| 最終ジャッジ日時 | 2023-07-16 15:51:00 |
| 合計ジャッジ時間 | 21,178 ms |
|
ジャッジサーバーID (参考情報) |
judge11 / judge13 |
| 純コード判定しない問題か言語 |
(要ログイン)
| ファイルパターン | 結果 |
|---|---|
| other | AC * 100 |
コンパイルメッセージ
Determining projects to restore... Restored /home/judge/data/code/main.csproj (in 118 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(136,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 (State.Turn + attackTurn + bestMoveTurn >= GetEnemyCollisionTurn(enemy)) continue; // 倒すのが間に合わない
var score = enemy.Power * 10000 / (attackTurn + bestMoveTurn);
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";
}
}
}
// todo 動かないときの衝突を回避する
// todo 横向きに動いたときの衝突を回避する
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;
}
}
inani_waon