結果
| 問題 |
No.5017 Tool-assisted Shooting
|
| ユーザー |
|
| 提出日時 | 2023-07-27 21:50:35 |
| 言語 | Rust (1.83.0 + proconio) |
| 結果 |
AC
|
| 実行時間 | 69 ms / 2,000 ms |
| コード長 | 8,320 bytes |
| コンパイル時間 | 6,159 ms |
| コンパイル使用メモリ | 158,208 KB |
| 実行使用メモリ | 24,396 KB |
| スコア | 3,245,574 |
| 平均クエリ数 | 879.44 |
| 最終ジャッジ日時 | 2023-07-27 21:50:54 |
| 合計ジャッジ時間 | 13,185 ms |
|
ジャッジサーバーID (参考情報) |
judge11 / judge12 |
| 純コード判定しない問題か言語 |
(要ログイン)
| ファイルパターン | 結果 |
|---|---|
| other | AC * 100 |
ソースコード
#![allow(non_snake_case)]
#![allow(unused_imports)]
#![allow(unused_macros)]
#![allow(clippy::comparison_chain)]
#![allow(clippy::nonminimal_bool)]
#![allow(clippy::neg_multiply)]
#![allow(clippy::type_complexity)]
#![allow(clippy::needless_range_loop)]
#![allow(dead_code)]
use std::{
cmp::Reverse,
collections::{BTreeMap, BTreeSet, BinaryHeap, VecDeque},
};
mod rnd {
static mut S: usize = 0;
static MAX: usize = 1e9 as usize;
#[inline]
pub fn init(seed: usize) {
unsafe {
if seed == 0 {
let t = std::time::SystemTime::now()
.duration_since(std::time::UNIX_EPOCH)
.unwrap()
.as_secs() as usize;
S = t
} else {
S = seed;
}
}
}
#[inline]
pub fn gen() -> usize {
unsafe {
if S == 0 {
init(0);
}
S ^= S << 7;
S ^= S >> 9;
S
}
}
#[inline]
pub fn gen_range(a: usize, b: usize) -> usize {
gen() % (b - a) + a
}
#[inline]
pub fn gen_bool() -> bool {
gen() & 1 == 1
}
#[inline]
pub fn gen_range_isize(a: usize) -> isize {
let mut x = (gen() % a) as isize;
if gen_bool() {
x *= -1;
}
x
}
#[inline]
pub fn gen_range_neg_wrapping(a: usize) -> usize {
let mut x = gen() % a;
if gen_bool() {
x = x.wrapping_neg();
}
x
}
#[inline]
pub fn gen_float() -> f64 {
((gen() % MAX) as f64) / MAX as f64
}
}
#[derive(Debug, Clone)]
struct TimeKeeper {
start_time: std::time::Instant,
time_threshold: f64,
}
impl TimeKeeper {
fn new(time_threshold: f64) -> Self {
TimeKeeper {
start_time: std::time::Instant::now(),
time_threshold,
}
}
#[inline]
fn isTimeOver(&self) -> bool {
let elapsed_time = self.start_time.elapsed().as_nanos() as f64 * 1e-9;
#[cfg(feature = "local")]
{
elapsed_time * 1.5 >= self.time_threshold
}
#[cfg(not(feature = "local"))]
{
elapsed_time >= self.time_threshold
}
}
#[inline]
fn get_time(&self) -> f64 {
let elapsed_time = self.start_time.elapsed().as_nanos() as f64 * 1e-9;
#[cfg(feature = "local")]
{
elapsed_time * 1.5
}
#[cfg(not(feature = "local"))]
{
elapsed_time
}
}
}
const H: usize = 60;
const W: usize = 25;
const TURN: usize = 1000;
const INF: isize = 1 << 60;
#[derive(Debug, Clone)]
struct State {
pos: (usize, usize),
S: usize,
field: Vec<Vec<(isize, usize)>>,
turn: usize,
}
impl State {
fn new() -> Self {
State {
pos: (12, 0),
S: 0,
field: vec![vec![(0, 0); W]; H + TURN + 10],
turn: 0,
}
}
fn update_field(&mut self, n: usize) {
let y = H + self.turn;
for _ in 0..n {
let v: Vec<usize> = read_vec();
let h = v[0] as isize;
let p = v[1];
let x = v[2];
self.field[y][x] = (h, p);
}
}
fn check_front_enemy(&self) -> bool {
let (now_x, now_y) = self.pos;
for y in now_y + 1..H + TURN + 10 {
if self.field[y][now_x] != (0, 0) {
let (h, _) = self.field[y][now_x];
let dy = y - now_y;
let level = (1 + self.S / 100) as isize;
let t = (h + level - 1) / level;
// t >= 1, dy >= 2
// dy = 1 => Game over
return dy > t as usize;
}
}
false
}
fn check_left_enemy(&self) -> isize {
let (now_x, now_y) = self.pos;
let x = (W + now_x - 1) % W;
for y in now_y + 1..H + TURN + 10 {
if self.field[y][x] != (0, 0) {
let (h, _) = self.field[y][x];
let dy = y - now_y;
let level = (1 + self.S / 100) as isize;
let t = (h + level - 1) / level;
if dy <= t as usize {
return INF + 1;
} else {
return t;
}
}
}
INF
}
fn check_right_enemy(&self) -> isize {
let (now_x, now_y) = self.pos;
let x = (now_x + 1) % W;
for y in now_y + 1..H + TURN + 10 {
if self.field[y][x] != (0, 0) {
let (h, _) = self.field[y][x];
let dy = y - now_y;
let level = (1 + self.S / 100) as isize;
let t = (h + level - 1) / level;
if dy <= t as usize {
return INF + 1;
} else {
return t;
}
}
}
INF
}
fn judge_collision_left(&self, d: usize) -> bool {
let (now_x, now_y) = self.pos;
self.field[now_y + d][(W + now_x - d) % W] != (0, 0)
}
fn judge_collision_right(&self, d: usize) -> bool {
let (now_x, now_y) = self.pos;
self.field[now_y + d][(now_x + d) % W] != (0, 0)
}
fn advance(&mut self, action: isize) {
self.pos.1 += 1;
self.pos.0 = (W as isize + action + self.pos.0 as isize) as usize % W;
self.attack();
self.turn += 1;
self.output(action);
}
fn attack(&mut self) {
let (now_x, now_y) = self.pos;
let x = now_x;
for y in now_y + 1..H + TURN + 10 {
if self.field[y][x] != (0, 0) {
let (h, p) = self.field[y][x];
let level = (1 + self.S / 100) as isize;
if h - level <= 0 {
self.S += p;
self.field[y][x] = (0, 0);
} else {
self.field[y][x].0 -= level;
}
return;
}
}
}
fn is_done(&self) -> bool {
self.turn == TURN
}
fn output(&self, action: isize) {
if action == 0 {
println!("S");
} else if action == -1 {
println!("L");
} else {
println!("R");
}
}
}
#[derive(Default)]
struct Solver {}
impl Solver {
fn solve(&mut self) {
let mut state = State::new();
#[cfg(feature = "local")]
{
eprintln!("Local Mode");
let _: Vec<usize> = read_vec();
}
while !state.is_done() {
let N: isize = read();
if N == -1 {
return;
}
state.update_field(N as usize);
if state.check_front_enemy()
|| (state.judge_collision_left(1) && state.judge_collision_right(1))
{
state.advance(0);
} else if state.judge_collision_left(1) {
state.advance(1);
} else if state.judge_collision_right(1) {
state.advance(-1);
} else {
let left = state.check_left_enemy();
let right = state.check_right_enemy();
if left == right {
state.advance(1);
} else if left < right {
state.advance(-1);
} else {
state.advance(1);
}
}
}
}
}
#[macro_export]
macro_rules! max {
($x: expr) => ($x);
($x: expr, $( $y: expr ),+) => {
std::cmp::max($x, max!($( $y ),+))
}
}
#[macro_export]
macro_rules! min {
($x: expr) => ($x);
($x: expr, $( $y: expr ),+) => {
std::cmp::min($x, min!($( $y ),+))
}
}
fn main() {
std::thread::Builder::new()
.stack_size(128 * 1024 * 1024)
.spawn(|| Solver::default().solve())
.unwrap()
.join()
.unwrap();
}
fn read<T: std::str::FromStr>() -> T {
let mut s = String::new();
std::io::stdin().read_line(&mut s).ok();
s.trim().parse().ok().unwrap()
}
fn read_vec<T: std::str::FromStr>() -> Vec<T> {
read::<String>()
.split_whitespace()
.map(|e| e.parse().ok().unwrap())
.collect()
}