結果
問題 | No.5017 Tool-assisted Shooting |
ユーザー | terry_u16 |
提出日時 | 2023-07-16 15:56:10 |
言語 | Rust (1.77.0 + proconio) |
結果 |
AC
|
実行時間 | 1,393 ms / 2,000 ms |
コード長 | 7,354 bytes |
コンパイル時間 | 1,500 ms |
コンパイル使用メモリ | 160,108 KB |
実行使用メモリ | 24,420 KB |
スコア | 3,530,489 |
平均クエリ数 | 1000.00 |
最終ジャッジ日時 | 2023-07-16 15:58:26 |
合計ジャッジ時間 | 133,549 ms |
ジャッジサーバーID (参考情報) |
judge15 / judge14 |
純コード判定しない問題か言語 |
(要ログイン)
テストケース
テストケース表示入力 | 結果 | 実行時間 実行使用メモリ |
---|---|---|
testcase_00 | AC | 1,253 ms
23,544 KB |
testcase_01 | AC | 1,319 ms
23,400 KB |
testcase_02 | AC | 1,132 ms
24,408 KB |
testcase_03 | AC | 1,251 ms
23,532 KB |
testcase_04 | AC | 1,208 ms
23,640 KB |
testcase_05 | AC | 1,209 ms
23,376 KB |
testcase_06 | AC | 1,283 ms
23,436 KB |
testcase_07 | AC | 1,288 ms
24,360 KB |
testcase_08 | AC | 1,223 ms
24,360 KB |
testcase_09 | AC | 1,237 ms
23,856 KB |
testcase_10 | AC | 1,250 ms
24,060 KB |
testcase_11 | AC | 1,195 ms
24,336 KB |
testcase_12 | AC | 1,242 ms
24,336 KB |
testcase_13 | AC | 1,267 ms
24,060 KB |
testcase_14 | AC | 1,272 ms
24,408 KB |
testcase_15 | AC | 1,208 ms
24,060 KB |
testcase_16 | AC | 1,219 ms
23,856 KB |
testcase_17 | AC | 1,309 ms
24,336 KB |
testcase_18 | AC | 1,256 ms
24,384 KB |
testcase_19 | AC | 1,279 ms
23,424 KB |
testcase_20 | AC | 1,284 ms
23,388 KB |
testcase_21 | AC | 1,311 ms
24,024 KB |
testcase_22 | AC | 1,130 ms
23,640 KB |
testcase_23 | AC | 1,175 ms
23,532 KB |
testcase_24 | AC | 1,280 ms
23,544 KB |
testcase_25 | AC | 1,329 ms
24,048 KB |
testcase_26 | AC | 1,238 ms
23,388 KB |
testcase_27 | AC | 1,216 ms
23,652 KB |
testcase_28 | AC | 1,313 ms
23,544 KB |
testcase_29 | AC | 1,181 ms
24,276 KB |
testcase_30 | AC | 1,190 ms
23,424 KB |
testcase_31 | AC | 1,231 ms
24,396 KB |
testcase_32 | AC | 1,290 ms
23,436 KB |
testcase_33 | AC | 1,341 ms
23,436 KB |
testcase_34 | AC | 1,238 ms
24,072 KB |
testcase_35 | AC | 1,261 ms
24,420 KB |
testcase_36 | AC | 1,200 ms
24,024 KB |
testcase_37 | AC | 1,283 ms
23,424 KB |
testcase_38 | AC | 1,286 ms
23,544 KB |
testcase_39 | AC | 1,294 ms
23,388 KB |
testcase_40 | AC | 1,295 ms
24,036 KB |
testcase_41 | AC | 1,225 ms
24,036 KB |
testcase_42 | AC | 1,256 ms
23,844 KB |
testcase_43 | AC | 1,273 ms
24,420 KB |
testcase_44 | AC | 1,292 ms
23,424 KB |
testcase_45 | AC | 1,276 ms
24,060 KB |
testcase_46 | AC | 1,309 ms
23,388 KB |
testcase_47 | AC | 1,176 ms
24,024 KB |
testcase_48 | AC | 1,313 ms
23,544 KB |
testcase_49 | AC | 1,230 ms
23,412 KB |
testcase_50 | AC | 1,258 ms
23,844 KB |
testcase_51 | AC | 1,278 ms
23,244 KB |
testcase_52 | AC | 1,289 ms
23,640 KB |
testcase_53 | AC | 1,279 ms
23,400 KB |
testcase_54 | AC | 1,268 ms
24,336 KB |
testcase_55 | AC | 1,228 ms
24,288 KB |
testcase_56 | AC | 1,299 ms
24,036 KB |
testcase_57 | AC | 1,216 ms
23,844 KB |
testcase_58 | AC | 1,259 ms
23,652 KB |
testcase_59 | AC | 1,318 ms
24,036 KB |
testcase_60 | AC | 1,270 ms
23,544 KB |
testcase_61 | AC | 1,222 ms
23,832 KB |
testcase_62 | AC | 1,209 ms
24,372 KB |
testcase_63 | AC | 1,271 ms
24,024 KB |
testcase_64 | AC | 1,295 ms
23,544 KB |
testcase_65 | AC | 1,393 ms
23,640 KB |
testcase_66 | AC | 1,307 ms
23,388 KB |
testcase_67 | AC | 1,262 ms
24,036 KB |
testcase_68 | AC | 1,260 ms
24,384 KB |
testcase_69 | AC | 1,241 ms
23,424 KB |
testcase_70 | AC | 1,276 ms
24,324 KB |
testcase_71 | AC | 1,274 ms
23,376 KB |
testcase_72 | AC | 1,176 ms
23,844 KB |
testcase_73 | AC | 1,289 ms
23,424 KB |
testcase_74 | AC | 1,171 ms
23,856 KB |
testcase_75 | AC | 1,292 ms
23,556 KB |
testcase_76 | AC | 1,273 ms
24,276 KB |
testcase_77 | AC | 1,332 ms
24,060 KB |
testcase_78 | AC | 1,278 ms
23,652 KB |
testcase_79 | AC | 1,254 ms
23,664 KB |
testcase_80 | AC | 1,311 ms
24,396 KB |
testcase_81 | AC | 1,232 ms
23,436 KB |
testcase_82 | AC | 1,259 ms
24,048 KB |
testcase_83 | AC | 1,227 ms
23,652 KB |
testcase_84 | AC | 1,274 ms
24,048 KB |
testcase_85 | AC | 1,305 ms
23,676 KB |
testcase_86 | AC | 1,267 ms
24,420 KB |
testcase_87 | AC | 1,227 ms
23,376 KB |
testcase_88 | AC | 1,315 ms
24,384 KB |
testcase_89 | AC | 1,281 ms
23,544 KB |
testcase_90 | AC | 1,302 ms
23,436 KB |
testcase_91 | AC | 1,328 ms
23,628 KB |
testcase_92 | AC | 1,158 ms
23,388 KB |
testcase_93 | AC | 1,301 ms
24,324 KB |
testcase_94 | AC | 1,188 ms
23,832 KB |
testcase_95 | AC | 1,286 ms
23,424 KB |
testcase_96 | AC | 1,308 ms
23,652 KB |
testcase_97 | AC | 1,265 ms
24,024 KB |
testcase_98 | AC | 1,258 ms
23,652 KB |
testcase_99 | AC | 1,264 ms
23,544 KB |
ソースコード
use std::{collections::VecDeque, io::Write}; 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<_>>() }; } pub trait ChangeMinMax { fn change_min(&mut self, v: Self) -> bool; fn change_max(&mut self, v: Self) -> bool; } impl<T: PartialOrd> ChangeMinMax for T { fn change_min(&mut self, v: T) -> bool { *self > v && { *self = v; true } } fn change_max(&mut self, v: T) -> bool { *self < v && { *self = v; true } } } const MAX_TURN: usize = 1000; const DEFAULT_SIMULATION_LEN: usize = 15; const HEIGHT: usize = 60; const WIDTH: usize = 25; const CENTER: usize = 12; const L: usize = !0; const C: usize = 0; const R: usize = 1; #[derive(Debug, Clone, Default)] struct State { column: usize, power: u32, raw_score: u32, board: Vec<u64>, turn: usize, enemies: Vec<VecDeque<Enemy>>, } impl State { fn new() -> Self { Self { column: CENTER, power: 100, raw_score: 0, board: vec![0; WIDTH], turn: 0, enemies: vec![VecDeque::new(); WIDTH], } } fn level(&self) -> u32 { self.power / 100 } fn move_enemy(&mut self) -> bool { for (i, b) in self.board.iter_mut().enumerate() { if *b & 1 > 0 { self.enemies[i].pop_front(); } *b >>= 1; } !self.is_crash() } fn spawn(&mut self, enemies: &[(u32, u32, usize)]) { for &(hp, power, col) in enemies { self.board[col] |= 1 << (HEIGHT - 1); self.enemies[col].push_back(Enemy::new(hp, power)); } } fn move_player(&mut self, direction: usize) -> bool { self.column = (self.column + direction + WIDTH) % WIDTH; !self.is_crash() } fn attack(&mut self) { let level = self.level(); if let Some(enemy) = self.enemies[self.column].front_mut() { enemy.damage(level); if enemy.hp == 0 { self.raw_score += enemy.init_hp; self.power += enemy.power; self.enemies[self.column].pop_front(); // ビットを下ろす let signed = self.board[self.column] as i64; let lsb = signed & -signed; self.board[self.column] ^= lsb as u64; } } } fn progress_turn(&mut self, enemies: &[(u32, u32, usize)], direction: usize) -> bool { let mut alive = true; alive &= self.move_enemy(); self.spawn(enemies); alive &= self.move_player(direction); self.attack(); self.turn += 1; alive } fn is_crash(&self) -> bool { (self.board[self.column] & 1) > 0 } fn score(&self) -> f64 { let raw_score_point = self.raw_score as i64 * MAX_TURN as i64; let power_point = self.power as i64 * (MAX_TURN - self.turn) as i64; let mut partial_power_point = 0.0; for enemy in self.enemies.iter().flatten() { let ratio = (enemy.init_hp - enemy.hp) as f64 / enemy.init_hp as f64; partial_power_point += enemy.power as f64 * ratio; } raw_score_point as f64 + power_point as f64 + partial_power_point } } #[derive(Debug, Clone, Copy, Default)] struct Enemy { hp: u32, init_hp: u32, power: u32, } impl Enemy { fn new(hp: u32, power: u32) -> Self { Self { hp, init_hp: hp, power, } } fn damage(&mut self, attack: u32) { self.hp = self.hp.saturating_sub(attack); } } fn main() { let mut state = State::new(); let mut turn = 0; while let Some(enemies) = read_spawns() { let mut current_states = vec![None; WIDTH]; current_states[state.column] = Some((state.clone(), C)); let simulation_len = DEFAULT_SIMULATION_LEN.min(MAX_TURN - turn); for iter in 0..simulation_len { let mut next_states: Vec<Option<(State, usize)>> = vec![None; WIDTH]; for state in current_states.iter() { if let Some((state, first_dir)) = state { for &dir in &[L, C, R] { let mut state = state.clone(); let is_alive = state.progress_turn(&enemies, dir); if !is_alive { continue; } let next_col = state.column; if next_states[next_col] .as_ref() .map_or(std::f64::MIN, |s| s.0.score()) < state.score() { let dir = if iter == 0 { dir } else { *first_dir }; next_states[next_col] = Some((state, dir)); } } } } current_states = next_states; } let mut best_score = std::f64::MIN; let mut best_dir = C; for s in current_states.iter() { if let Some((state, dir)) = s { if best_score.change_max(state.score()) { best_dir = *dir; } } } eprintln!("power: {}", state.power); eprintln!("score: {}", state.raw_score); eprintln!("turn: {}", turn + 1); eprintln!("best_score: {}", best_score); eprintln!(""); write_direction(best_dir); state.progress_turn(&enemies, best_dir); turn += 1; if turn == MAX_TURN { break; } } } fn read_spawns() -> 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) } fn write_direction(direction: usize) { match direction { L => println!("L"), C => println!("S"), R => println!("R"), _ => unreachable!(), } std::io::stdout().flush().unwrap(); }