結果

問題 No.5024 魔法少女うなと宝集め
コンテスト
ユーザー tomerun
提出日時 2026-05-02 17:48:10
言語 Rust
(1.94.0 + proconio + num + itertools)
コンパイル:
/usr/bin/rustc_custom
実行:
./target/release/main
結果
AC  
実行時間 174 ms / 2,000 ms
コード長 11,047 bytes
記録
記録タグの例:
初AC ショートコード 純ショートコード 純主流ショートコード 最速実行時間
コンパイル時間 2,365 ms
コンパイル使用メモリ 202,072 KB
実行使用メモリ 6,400 KB
スコア 2,111,020
最終ジャッジ日時 2026-05-02 17:49:30
合計ジャッジ時間 8,594 ms
ジャッジサーバーID
(参考情報)
judge3_1 / judge2_1
純コード判定しない問題か言語
このコードへのチャレンジ
(要ログイン)
ファイルパターン 結果
other AC * 50
権限があれば一括ダウンロードができます

ソースコード

diff #
raw source code

#![allow(unused_imports)]
#![allow(dead_code)]
#![allow(non_snake_case)]
use std::array;
use std::env;
use std::io::{self, BufRead, BufReader, Read, Stdin};
use std::mem;
use std::str::FromStr;
use std::string::String;
use std::time;

const TIMELIMIT: u64 = 900;
const INF: usize = 1 << 28;
const N: usize = 20;

#[derive(Debug)]
pub struct Scanner<R> {
    reader: BufReader<R>,
}

fn scanner() -> Scanner<Stdin> {
    Scanner::new(io::stdin())
}

impl<R: io::Read> Scanner<R> {
    pub fn new(read: R) -> Scanner<R> {
        Scanner { reader: BufReader::new(read) }
    }

    pub fn next_str(&mut self) -> Option<String> {
        let mut buf = [0; 1];
        let size = self.reader.read(&mut buf).unwrap();
        if size == 0 {
            None
        } else {
            self.skip_whitespace(&mut buf)?;
            let mut v = vec![buf[0]];
            loop {
                let size = self.reader.read(&mut buf).unwrap();
                if size == 0 || buf[0].is_ascii_whitespace() {
                    break;
                }
                v.push(buf[0]);
            }
            Some(String::from_utf8(v).unwrap())
        }
    }

    pub fn next_line(&mut self) -> String {
        let mut line = String::new();
        self.reader.read_line(&mut line).unwrap();
        if let Some(s) = line.strip_suffix("\n") { s.to_string() } else { line }
    }

    pub fn next_as<S: FromStr>(&mut self) -> Option<S> {
        let s = self.next_str()?;
        S::from_str(&s).ok()
    }

    pub fn str(&mut self) -> String {
        self.next_str().unwrap()
    }

    pub fn i32(&mut self) -> i32 {
        self.next_as::<i32>().unwrap()
    }

    pub fn u32(&mut self) -> u32 {
        self.next_as::<u32>().unwrap()
    }

    pub fn u64(&mut self) -> u64 {
        self.next_as::<u64>().unwrap()
    }

    pub fn usize(&mut self) -> usize {
        self.next_as::<usize>().unwrap()
    }

    fn skip_whitespace(&mut self, mut buf: &mut [u8]) -> Option<u8> {
        loop {
            if !buf[0].is_ascii_whitespace() {
                return Some(buf[0]);
            }
            let size = self.reader.read(&mut buf).unwrap();
            if size == 0 {
                return None;
            }
        }
    }
}

#[derive(Debug)]
struct Timer {
    start_time: time::Instant,
    limit: time::Instant,
    before_time: Option<time::Instant>,
    worst_time: time::Duration,
}

impl Timer {
    fn new(tl: u64) -> Timer {
        let start_time = time::Instant::now();
        Timer {
            start_time,
            limit: start_time + time::Duration::from_millis(tl),
            before_time: None,
            worst_time: time::Duration::from_millis(0),
        }
    }

    fn elapsed(&self) -> u64 {
        self.start_time.elapsed().as_millis() as u64
    }

    fn checkpoint(&mut self) {
        if let Some(before_time) = self.before_time {
            let elapsed = before_time.elapsed();
            self.worst_time = self.worst_time.max(elapsed);
        }
        self.before_time = Some(time::Instant::now());
    }

    fn tl(&self) -> u64 {
        (self.limit - self.start_time).as_millis() as u64
    }

    fn tl_exceeded(&self) -> bool {
        self.limit < time::Instant::now()
    }

    fn should_stop(&self) -> bool {
        self.limit < time::Instant::now() + self.worst_time
    }
}

struct XorShift32 {
    state: u32,
}

impl XorShift32 {
    fn from_seed(seed: u32) -> Self {
        let initial_state = if seed == 0 { 1 } else { seed };
        XorShift32 { state: initial_state }
    }

    fn next_u32(&mut self) -> u32 {
        let mut x = self.state;
        x ^= x << 13;
        x ^= x >> 17;
        x ^= x << 5;
        self.state = x;
        x
    }

    fn next_u64(&mut self) -> u64 {
        ((self.next_u32() as u64) << 32) | (self.next_u32() as u64)
    }

    fn next_f64(&mut self) -> f64 {
        self.next_u32() as f64 / (u32::MAX as f64 + 1.0)
    }
}

#[derive(Debug, Clone, Copy, Default)]
struct Pos {
    y: usize,
    x: usize,
}

impl Pos {
    fn rot(&mut self) {
        let tmp = self.y;
        self.y = self.x;
        self.x = N - 1 - tmp;
    }
}

#[derive(Debug, Clone)]
struct Input {
    T: usize,
    A: Vec<Vec<usize>>,
}

impl Input {
    fn new() -> Input {
        let mut sc = scanner();
        let _ = sc.usize();
        let T = sc.usize();
        let mut A = vec![vec![0; N]; N];
        for i in 0..N {
            for j in 0..N {
                A[i][j] = sc.usize();
            }
        }
        Input { T, A }
    }
}

#[derive(Debug, Clone)]
struct Result {
    path: Vec<Pos>,
    score: usize,
}

impl Result {
    fn new(path: Vec<Pos>, score: usize) -> Result {
        Result { path, score }
    }

    fn new_empty() -> Result {
        Result { path: vec![], score: 0 }
    }

    fn output(&self) {
        println!("{}", self.path.len());
        for pos in &self.path {
            println!("{} {}", pos.y, pos.x);
        }
    }
}

struct Solver {
    input: Input,
    timer: Timer,
    rng: XorShift32,
}

impl Solver {
    fn new(input: Input) -> Solver {
        let tl = env::var("TL").map_or(TIMELIMIT, |v| v.parse().unwrap());
        let timer = Timer::new(tl);
        let rng = XorShift32::from_seed(2);
        Solver { input, timer, rng }
    }

    fn solve(&mut self) -> Result {
        let mut best_res = Result::new_empty();

        for i in 0..4 {
            let mut res = self.solve_dp();
            if res.score > best_res.score {
                for pos in &mut res.path {
                    for _ in 0..(4 - i) {
                        pos.rot();
                    }
                }
                eprintln!("rot:{:?} score:{:?}", i, res.score);
                best_res = res;
            }
            // rot A
            let mut tmp_A = vec![vec![0; N]; N];
            for y in 0..N {
                for x in 0..N {
                    tmp_A[y][x] = self.input.A[N - 1 - x][y];
                }
            }
            self.input.A = tmp_A;
        }

        best_res
    }

    fn solve_dp(&mut self) -> Result {
        let mut acc = vec![];
        for i in 0..N {
            let mut row = vec![0];
            for j in 0..N {
                row.push(row.last().unwrap() + self.input.A[i][j]);
            }
            acc.push(row);
        }
        let mut dp = vec![vec![vec![(0, 0, 0); self.input.T + 1]; N]; N];
        for i in 0..N {
            for l in 0..N {
                for r in l..N {
                    let sum = acc[i][r + 1] - acc[i][l];
                    if r - l + 1 <= self.input.T && sum > dp[i][r][r - l + 1].0 {
                        dp[i][r][r - l + 1] = (sum, l, INF);
                    }
                    if r - l + 1 <= self.input.T && sum > dp[i][l][r - l + 1].0 {
                        dp[i][l][r - l + 1] = (sum, r, INF);
                    }
                }
            }
            if i == 0 {
                continue;
            }
            for px in 0..N {
                for pt in 0..self.input.T {
                    if dp[i - 1][px][pt].0 == 0 {
                        continue;
                    }
                    let ppx = dp[i - 1][px][pt].1;
                    for nx in 0..px {
                        let sum = acc[i][px + 1] - acc[i][nx] + dp[i - 1][px][pt].0;
                        let nt = pt + px - nx + 1;
                        if nt <= self.input.T && sum > dp[i][nx][nt].0 {
                            dp[i][nx][nt] = (sum, px, INF);
                        }
                        for ux in nx..px - 1 {
                            if ux + 1 < ppx {
                                let sum = acc[i][px + 1] - acc[i][nx]
                                    + dp[i - 1][px][pt].0
                                    + self.input.A[i - 1][ux]
                                    + self.input.A[i - 1][ux + 1];
                                let nt = pt + px - nx + 3;
                                if nt <= self.input.T && sum > dp[i][nx][nt].0 {
                                    dp[i][nx][nt] = (sum, px, ux);
                                }
                            }
                        }
                    }
                    for nx in (px + 1)..N {
                        let sum = acc[i][nx + 1] - acc[i][px] + dp[i - 1][px][pt].0;
                        let nt = pt + nx - px + 1;
                        if nt <= self.input.T && sum > dp[i][nx][nt].0 {
                            dp[i][nx][nt] = (sum, px, INF);
                        }
                        for ux in px + 1..nx - 1 {
                            if ppx < ux {
                                let sum = acc[i][nx + 1] - acc[i][px]
                                    + dp[i - 1][px][pt].0
                                    + self.input.A[i - 1][ux]
                                    + self.input.A[i - 1][ux + 1];
                                let nt = pt + nx - px + 3;
                                if nt <= self.input.T && sum > dp[i][nx][nt].0 {
                                    dp[i][nx][nt] = (sum, px, ux + 1);
                                }
                            }
                        }
                    }
                }
            }
        }
        let mut max_y = 0;
        let mut max_x = 0;
        let mut max_v = 0;
        let mut max_t = 0;
        for i in 0..N {
            for j in 0..N {
                for t in 0..=self.input.T {
                    if dp[i][j][t].0 > max_v {
                        max_v = dp[i][j][t].0;
                        max_y = i;
                        max_x = j;
                        max_t = t;
                    }
                }
            }
        }
        eprintln!("score:{:?} y:{} x:{}", max_v, max_y, max_x);
        let mut path = vec![];
        while max_t > 0 {
            let prev_x = dp[max_y][max_x][max_t].1;
            let ux = dp[max_y][max_x][max_t].2;
            if prev_x < max_x {
                for x in (prev_x..=max_x).rev() {
                    path.push(Pos { y: max_y, x });
                    if x == ux {
                        path.push(Pos { y: max_y - 1, x });
                        path.push(Pos { y: max_y - 1, x: x - 1 });
                    }
                }
            } else {
                for x in max_x..=prev_x {
                    path.push(Pos { y: max_y, x });
                    if x == ux {
                        path.push(Pos { y: max_y - 1, x });
                        path.push(Pos { y: max_y - 1, x: x + 1 });
                    }
                }
            }
            max_t -= max_x.abs_diff(prev_x) + 1;
            if ux != INF {
                max_t -= 2;
            }
            max_y = max_y.wrapping_sub(1);
            max_x = prev_x;
        }
        Result::new(path, max_v)
    }
}

fn main() {
    let input = Input::new();
    let mut solver = Solver::new(input.clone());
    let best_res = solver.solve();
    best_res.output();
    eprintln!("final_score:{:?}", best_res.score);
}
0