結果
| 問題 |
No.5017 Tool-assisted Shooting
|
| コンテスト | |
| ユーザー |
tamura-up
|
| 提出日時 | 2023-07-21 13:25:01 |
| 言語 | Rust (1.83.0 + proconio) |
| 結果 |
AC
|
| 実行時間 | 120 ms / 2,000 ms |
| コード長 | 6,199 bytes |
| コンパイル時間 | 4,578 ms |
| コンパイル使用メモリ | 161,568 KB |
| 実行使用メモリ | 24,360 KB |
| スコア | 4,054,893 |
| 平均クエリ数 | 1000.00 |
| 最終ジャッジ日時 | 2023-07-21 13:25:21 |
| 合計ジャッジ時間 | 18,012 ms |
|
ジャッジサーバーID (参考情報) |
judge12 / judge15 |
| 純コード判定しない問題か言語 |
(要ログイン)
| ファイルパターン | 結果 |
|---|---|
| other | AC * 100 |
ソースコード
#![allow(unused_imports)]
#![allow(unused_macros)]
#![allow(dead_code)]
#![allow(non_snake_case)]
use std::cmp::{max, min};
use std::collections::VecDeque;
use std::fs::read;
use std::io::Write;
use std::time::Instant;
const Y: usize = 60;
const X: usize = 25;
const NEG1: usize = !0;
// src: https://yukicoder.me/submissions/892593
//
// let x = get!(i32); // 1行の i32 の入力を受け取る
// let x = get!(i32;2); // 2行の i32 の入力を受け取る
//
// tuple
// let x = get!(i32,i32,i32); // (i32, i32, i32 )のタプルを受け取る
// let x = get!(i32,i32,i32;2); // 2行 (i32, i32, i32 )のタプルを受け取る
macro_rules! get {
($t:ty) => {
{
let mut line: String = String::new();
std::io::stdin().read_line(&mut line).unwrap();
line.trim().parse::<$t>().unwrap()
}
};
($($t:ty),*) => {
{
let mut line: String = String::new();
std::io::stdin().read_line(&mut line).unwrap();
let mut iter = line.split_whitespace();
(
$(iter.next().unwrap().parse::<$t>().unwrap(),)*
)
}
};
($t:ty; $n:expr) => {
(0..$n).map(|_|
get!($t)
).collect::<Vec<_>>()
};
($($t:ty),*; $n:expr) => {
(0..$n).map(|_|
get!($($t),*)
).collect::<Vec<_>>()
};
($t:ty ;;) => {
{
let mut line: String = String::new();
std::io::stdin().read_line(&mut line).unwrap();
line.split_whitespace()
.map(|t| t.parse::<$t>().unwrap())
.collect::<Vec<_>>()
}
};
($t:ty ;; $n:expr) => {
(0..$n).map(|_| get!($t ;;)).collect::<Vec<_>>()
};
}
fn read_input() -> Option<Vec<(u32, u32, usize)>> {
let n = get!(i32);
if n < 0 {
return None;
}
let mut enemies = vec![];
for _ in 0..n {
enemies.push(get!(u32,u32,usize));
}
Some(enemies)
}
#[derive(Clone, Copy, Debug)]
struct Enemy {
hp: u32,
pw: u32,
y: usize,
}
struct EnemyPool {
col: Vec<VecDeque<Enemy>>,
}
impl EnemyPool {
fn new() -> EnemyPool {
EnemyPool { col: vec![VecDeque::new(); X] }
}
fn add(&mut self, enemy: &(u32, u32, usize)) {
self.col[enemy.2].push_back(Enemy { hp: enemy.0, pw: enemy.1, y: Y - 1 });
}
fn step(&mut self) {
for i in 0..self.col.len() {
if let Some(f) = self.col[i].front() {
if f.y == 0 { self.col[i].pop_front(); }
}
for j in 0..self.col[i].len() {
self.col[i][j].y -= 1;
}
}
}
fn get_first(&self, x: usize) -> Option<&Enemy> {
return self.col[x].front();
}
fn attack(&mut self, x: usize, level: u32) -> u32 {
let mut res = 0;
if self.col[x].len() <= 0 { return 0; }
if self.col[x][0].hp <= level {
res = self.col[x][0].pw;
self.col[x].pop_front();
} else {
self.col[x][0].hp -= level;
eprintln!("x:{} hp:{}",x,self.col[x][0].hp);
}
res
}
}
fn main() {
let mut iter = 1;
let mut pool = EnemyPool::new();
let mut x = 12;
let mut level: u32 = 1;
let mut score = 0;
while let Some(enemies) = read_input() {
eprintln!("iter: {}, x:{}, level:{}, score:{}", iter, x, level, score);
// if iter==861{
// break;
// }
pool.step();
for e in enemies {
pool.add(&e);
}
if let Some(e) = pool.get_first(x) {
if e.y == 0 {
break;
}
}
// 移動
let mut best = (-1.0, 0, x);
for di in [!0, 1] {
let mut ni = x;
'outer: for step in 0..X / 2 {
let i = ni;
for en in &pool.col[i] {
if step>0 && en.y==step-1{
break 'outer;
}
if en.y >= step {
let att = level * (en.y - max(step,1) + 1) as u32;
if en.hp <= att {
let cnt = (en.hp + level - 1) / level;
let score = en.pw as f64 / (step as u32 + cnt) as f64;
if best.0 < score {
best.0 = score;
best.1 = if step == 0 { 0 } else { di };
best.2 = i;
if iter==860 && i==18{
eprintln!("attack cnt:{}, att:{}",cnt,att);
}
}
} else if en.y == step {
eprintln!("lim:{} (di:{})", i,di);
break 'outer;
}
break;
}
}
ni = ni.wrapping_add(di);
ni = if ni == X { 0 } else if ni > X { X - 1 } else { ni };
}
}
eprintln!("sel:{:?}",best);
{
let d: usize = best.1;
let mv = match d {
0 => "S",
1 => "R",
NEG1 => "L",
_ => "S"
};
println!("{}", mv);
x = x.wrapping_add(d);
x = if x == X { 0 } else if x > X { X - 1 } else { x };
}
// 攻撃
score += pool.attack(x, level);
level = score / 100 + 1;
std::io::stdout().flush().unwrap();
if iter >= 1000 { break; }
iter += 1;
}
}
pub trait SetMinMax {
fn setmin(&mut self, v: Self) -> bool;
fn setmax(&mut self, v: Self) -> bool;
}
impl<T> SetMinMax for T where T: PartialOrd {
fn setmin(&mut self, v: T) -> bool {
*self > v && {
*self = v;
true
}
}
fn setmax(&mut self, v: T) -> bool {
*self < v && {
*self = v;
true
}
}
}
tamura-up