Submission #42958368


Source Code Expand

#![allow(non_snake_case)]

use bitset_fixed::BitSet;
use itertools::Itertools;
use proconio::*;
use std::collections::HashSet;

fn main() {
    get_time();
    let input = read_input();
    let out = solve(&input);
    write_output(&out);
    eprintln!("Time = {:.3}", get_time());
}

const W: usize = 2000;

fn solve(input: &Input) -> Output {
    // 一番小さいボールから順に1つずつ適切な場所へ運ぶのを1ステップとしてビームサーチをする
    // 評価値は(手数, 下方向にボールを動かすたびにその数字を減算したもの)の辞書順
    let mut beam = vec![State {
        bs: input.bs.clone(),
        id: !0,
        score: (0, 0),
        used: BitSet::new(N2),
    }];
    let mut trace = Trace::new();
    let mut dist = [((1000000000, 0), !0); N2];
    for i in 0..N2 as i32 {
        eprintln!("{}: {}", i, beam[0].score.0);
        let mut trace2 = Trace::new();
        // 高速化のため、次の状態を列挙するのではなく評価値と遷移方法のみを列挙する
        // (評価値, 現在のビームの何番目からか, 運ぶ先x, 運ぶ先y, 復元用ID)
        let mut next_move = vec![];
        let pos: Vec<(usize, usize)> = beam.iter().map(|s| pos(&s.bs, i)).collect_vec();
        for b in 0..beam.len() {
            let bs = &beam[b].bs;
            let (x0, y0) = pos[b];
            dist[id(x0, y0)] = ((0, 0), !0);
            if x0 == 0 || (y0 == 0 || bs[id(x0 - 1, y0 - 1)] < i) && (y0 == x0 || bs[id(x0 - 1, y0)] < i) {
                next_move.push((beam[b].score, b, x0, y0, !0));
                continue;
            }
            // 上方向への(評価値の観点で)最適な運び方をDPで計算する
            for dx in 1..=x0 {
                let x = x0 - dx;
                let mut ok = false;
                for y in y0 - y0.min(dx)..=y0.min(x) {
                    if bs[id(x, y)] < i {
                        continue;
                    }
                    let mut d = (1000000000, 0);
                    let mut prev = (0, !0);
                    if y + dx != y0 {
                        let d2 = dist[id(x + 1, y)];
                        if d.setmin((d2.0 .0 + 1, d2.0 .1 - bs[id(x, y)])) {
                            prev = (0, d2.1);
                            ok = true;
                        }
                    }
                    if y0 != y {
                        let d2 = dist[id(x + 1, y + 1)];
                        if d.setmin((d2.0 .0 + 1, d2.0 .1 - bs[id(x, y)])) {
                            prev = (1, d2.1);
                            ok = true;
                        }
                    }
                    let k = if d.0 < 1000000000 { trace2.add(prev.0, prev.1) } else { !0 };
                    dist[id(x, y)] = (d, k);
                    // 運び方はDPで最適なもの一つに絞るが、運び先に応じてそれぞれ別の遷移とする
                    if d.0 < 1000000000 && (x == 0 || (y == 0 || bs[id(x - 1, y - 1)] < i) && (y == x || bs[id(x - 1, y)] < i)) {
                        next_move.push((
                            (beam[b].score.0 + dist[id(x, y)].0 .0, beam[b].score.1 + dist[id(x, y)].0 .1),
                            b,
                            x,
                            y,
                            k,
                        ));
                    }
                }
                if !ok {
                    break;
                }
            }
        }
        next_move.sort_by_key(|a| a.0);
        let mut next = vec![];
        let mut set = HashSet::new();
        for (score, b, x, y, tid) in next_move {
            // 多様性確保のため、既に埋まった座標の集合が同じものは1つまでしか選ばないようにする
            let mut used = beam[b].used.clone();
            used.set(id(x, y), true);
            if !set.insert(used.clone()) {
                continue;
            }
            let (mut x, mut y) = pos[b];
            let mut k = beam[b].id;
            let mut bs = beam[b].bs.clone();
            for dy in trace2.get(tid) {
                k = trace.add(((x, y), (x - 1, y - dy)), k);
                bs.swap(id(x, y), id(x - 1, y - dy));
                x -= 1;
                y -= dy;
            }
            next.push(State { score, bs, id: k, used });
            if next.len() == W {
                break;
            }
        }
        beam = next;
    }
    trace.get(beam[0].id)
}

fn pos(bs: &Vec<i32>, i: i32) -> (usize, usize) {
    for x in 0..N {
        for y in 0..=x {
            if bs[id(x, y)] == i {
                return (x, y);
            }
        }
    }
    panic!();
}

struct State {
    bs: Vec<i32>,
    id: usize,
    score: (i32, i32),
    used: BitSet,
}

// 入出力と得点計算

const N: usize = 30;
const N2: usize = N * (N + 1) / 2;

fn id(x: usize, y: usize) -> usize {
    x * (x + 1) / 2 + y
}

pub type Output = Vec<((usize, usize), (usize, usize))>;

#[derive(Clone, Debug)]
pub struct Input {
    pub bs: Vec<i32>,
}

pub fn read_input() -> Input {
    input! {
        bs: [i32; N2]
    }
    Input { bs }
}

pub fn write_output(out: &Output) {
    println!("{}", out.len());
    for &((x1, y1), (x2, y2)) in out {
        println!("{} {} {} {}", x1, y1, x2, y2);
    }
}

// ここからライブラリ

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
        }
    }
}

#[macro_export]
macro_rules! mat {
	($($e:expr),*) => { vec![$($e),*] };
	($($e:expr,)*) => { vec![$($e),*] };
	($e:expr; $d:expr) => { vec![$e; $d] };
	($e:expr; $d:expr $(; $ds:expr)+) => { vec![mat![$e $(; $ds)*]; $d] };
}

pub fn get_time() -> f64 {
    static mut STIME: f64 = -1.0;
    let t = std::time::SystemTime::now().duration_since(std::time::UNIX_EPOCH).unwrap();
    let ms = t.as_secs() as f64 + t.subsec_nanos() as f64 * 1e-9;
    unsafe {
        if STIME < 0.0 {
            STIME = ms;
        }
        // ローカル環境とジャッジ環境の実行速度差はget_timeで吸収しておくと便利
        #[cfg(feature = "local")]
        {
            (ms - STIME) * 1.3
        }
        #[cfg(not(feature = "local"))]
        {
            ms - STIME
        }
    }
}

struct Trace<T: Copy> {
    log: Vec<(T, usize)>,
}

impl<T: Copy> Trace<T> {
    fn new() -> Self {
        Trace { log: vec![] }
    }
    fn add(&mut self, c: T, p: usize) -> usize {
        self.log.push((c, p));
        self.log.len() - 1
    }
    fn get(&self, mut i: usize) -> Vec<T> {
        let mut out = vec![];
        while i != !0 {
            out.push(self.log[i].0);
            i = self.log[i].1;
        }
        out.reverse();
        out
    }
}

Submission Info

Submission Time
Task A - Pyramid Sorting
User wata_admin
Language Rust (1.42.0)
Score 13575560
Code Size 7282 Byte
Status AC
Exec Time 1821 ms
Memory 178068 KiB

Judge Result

Set Name test_ALL
Score / Max Score 13575560 / 15000000
Status
AC × 150
Set Name Test Cases
test_ALL test_0000.txt, test_0001.txt, test_0002.txt, test_0003.txt, test_0004.txt, test_0005.txt, test_0006.txt, test_0007.txt, test_0008.txt, test_0009.txt, test_0010.txt, test_0011.txt, test_0012.txt, test_0013.txt, test_0014.txt, test_0015.txt, test_0016.txt, test_0017.txt, test_0018.txt, test_0019.txt, test_0020.txt, test_0021.txt, test_0022.txt, test_0023.txt, test_0024.txt, test_0025.txt, test_0026.txt, test_0027.txt, test_0028.txt, test_0029.txt, test_0030.txt, test_0031.txt, test_0032.txt, test_0033.txt, test_0034.txt, test_0035.txt, test_0036.txt, test_0037.txt, test_0038.txt, test_0039.txt, test_0040.txt, test_0041.txt, test_0042.txt, test_0043.txt, test_0044.txt, test_0045.txt, test_0046.txt, test_0047.txt, test_0048.txt, test_0049.txt, test_0050.txt, test_0051.txt, test_0052.txt, test_0053.txt, test_0054.txt, test_0055.txt, test_0056.txt, test_0057.txt, test_0058.txt, test_0059.txt, test_0060.txt, test_0061.txt, test_0062.txt, test_0063.txt, test_0064.txt, test_0065.txt, test_0066.txt, test_0067.txt, test_0068.txt, test_0069.txt, test_0070.txt, test_0071.txt, test_0072.txt, test_0073.txt, test_0074.txt, test_0075.txt, test_0076.txt, test_0077.txt, test_0078.txt, test_0079.txt, test_0080.txt, test_0081.txt, test_0082.txt, test_0083.txt, test_0084.txt, test_0085.txt, test_0086.txt, test_0087.txt, test_0088.txt, test_0089.txt, test_0090.txt, test_0091.txt, test_0092.txt, test_0093.txt, test_0094.txt, test_0095.txt, test_0096.txt, test_0097.txt, test_0098.txt, test_0099.txt, test_0100.txt, test_0101.txt, test_0102.txt, test_0103.txt, test_0104.txt, test_0105.txt, test_0106.txt, test_0107.txt, test_0108.txt, test_0109.txt, test_0110.txt, test_0111.txt, test_0112.txt, test_0113.txt, test_0114.txt, test_0115.txt, test_0116.txt, test_0117.txt, test_0118.txt, test_0119.txt, test_0120.txt, test_0121.txt, test_0122.txt, test_0123.txt, test_0124.txt, test_0125.txt, test_0126.txt, test_0127.txt, test_0128.txt, test_0129.txt, test_0130.txt, test_0131.txt, test_0132.txt, test_0133.txt, test_0134.txt, test_0135.txt, test_0136.txt, test_0137.txt, test_0138.txt, test_0139.txt, test_0140.txt, test_0141.txt, test_0142.txt, test_0143.txt, test_0144.txt, test_0145.txt, test_0146.txt, test_0147.txt, test_0148.txt, test_0149.txt
Case Name Status Exec Time Memory
test_0000.txt AC 1776 ms 176324 KiB
test_0001.txt AC 1624 ms 154164 KiB
test_0002.txt AC 1661 ms 162564 KiB
test_0003.txt AC 1644 ms 158992 KiB
test_0004.txt AC 1628 ms 157148 KiB
test_0005.txt AC 1689 ms 165000 KiB
test_0006.txt AC 1704 ms 169280 KiB
test_0007.txt AC 1722 ms 167556 KiB
test_0008.txt AC 1577 ms 149472 KiB
test_0009.txt AC 1658 ms 153536 KiB
test_0010.txt AC 1723 ms 163920 KiB
test_0011.txt AC 1679 ms 166560 KiB
test_0012.txt AC 1671 ms 162692 KiB
test_0013.txt AC 1716 ms 160464 KiB
test_0014.txt AC 1685 ms 173352 KiB
test_0015.txt AC 1695 ms 163092 KiB
test_0016.txt AC 1686 ms 166388 KiB
test_0017.txt AC 1691 ms 171152 KiB
test_0018.txt AC 1710 ms 163884 KiB
test_0019.txt AC 1632 ms 166416 KiB
test_0020.txt AC 1679 ms 167444 KiB
test_0021.txt AC 1644 ms 160148 KiB
test_0022.txt AC 1662 ms 164400 KiB
test_0023.txt AC 1756 ms 172148 KiB
test_0024.txt AC 1672 ms 155752 KiB
test_0025.txt AC 1594 ms 159484 KiB
test_0026.txt AC 1686 ms 160328 KiB
test_0027.txt AC 1620 ms 156684 KiB
test_0028.txt AC 1680 ms 163252 KiB
test_0029.txt AC 1644 ms 160780 KiB
test_0030.txt AC 1754 ms 168728 KiB
test_0031.txt AC 1727 ms 170912 KiB
test_0032.txt AC 1693 ms 159232 KiB
test_0033.txt AC 1709 ms 160732 KiB
test_0034.txt AC 1710 ms 164820 KiB
test_0035.txt AC 1673 ms 166924 KiB
test_0036.txt AC 1684 ms 161344 KiB
test_0037.txt AC 1608 ms 155760 KiB
test_0038.txt AC 1722 ms 170728 KiB
test_0039.txt AC 1672 ms 162320 KiB
test_0040.txt AC 1530 ms 151180 KiB
test_0041.txt AC 1703 ms 164728 KiB
test_0042.txt AC 1678 ms 163860 KiB
test_0043.txt AC 1709 ms 161388 KiB
test_0044.txt AC 1631 ms 161856 KiB
test_0045.txt AC 1675 ms 166708 KiB
test_0046.txt AC 1660 ms 160088 KiB
test_0047.txt AC 1798 ms 170172 KiB
test_0048.txt AC 1694 ms 160032 KiB
test_0049.txt AC 1689 ms 162640 KiB
test_0050.txt AC 1729 ms 169260 KiB
test_0051.txt AC 1703 ms 156504 KiB
test_0052.txt AC 1625 ms 158304 KiB
test_0053.txt AC 1651 ms 159184 KiB
test_0054.txt AC 1720 ms 170184 KiB
test_0055.txt AC 1701 ms 166116 KiB
test_0056.txt AC 1728 ms 164108 KiB
test_0057.txt AC 1786 ms 171400 KiB
test_0058.txt AC 1821 ms 171840 KiB
test_0059.txt AC 1744 ms 162912 KiB
test_0060.txt AC 1744 ms 168748 KiB
test_0061.txt AC 1751 ms 167328 KiB
test_0062.txt AC 1704 ms 163084 KiB
test_0063.txt AC 1682 ms 164624 KiB
test_0064.txt AC 1655 ms 161004 KiB
test_0065.txt AC 1715 ms 164100 KiB
test_0066.txt AC 1750 ms 166604 KiB
test_0067.txt AC 1734 ms 168212 KiB
test_0068.txt AC 1698 ms 161668 KiB
test_0069.txt AC 1675 ms 163796 KiB
test_0070.txt AC 1756 ms 164620 KiB
test_0071.txt AC 1663 ms 154672 KiB
test_0072.txt AC 1704 ms 162188 KiB
test_0073.txt AC 1702 ms 163200 KiB
test_0074.txt AC 1692 ms 157220 KiB
test_0075.txt AC 1668 ms 162964 KiB
test_0076.txt AC 1790 ms 168644 KiB
test_0077.txt AC 1659 ms 160716 KiB
test_0078.txt AC 1699 ms 157380 KiB
test_0079.txt AC 1716 ms 157372 KiB
test_0080.txt AC 1731 ms 166548 KiB
test_0081.txt AC 1709 ms 163528 KiB
test_0082.txt AC 1634 ms 153960 KiB
test_0083.txt AC 1669 ms 163928 KiB
test_0084.txt AC 1701 ms 165024 KiB
test_0085.txt AC 1677 ms 159980 KiB
test_0086.txt AC 1731 ms 167008 KiB
test_0087.txt AC 1725 ms 167568 KiB
test_0088.txt AC 1710 ms 168532 KiB
test_0089.txt AC 1723 ms 165820 KiB
test_0090.txt AC 1706 ms 166108 KiB
test_0091.txt AC 1659 ms 164028 KiB
test_0092.txt AC 1658 ms 163436 KiB
test_0093.txt AC 1617 ms 164108 KiB
test_0094.txt AC 1684 ms 169484 KiB
test_0095.txt AC 1607 ms 152812 KiB
test_0096.txt AC 1708 ms 170036 KiB
test_0097.txt AC 1688 ms 162444 KiB
test_0098.txt AC 1666 ms 164056 KiB
test_0099.txt AC 1714 ms 163760 KiB
test_0100.txt AC 1672 ms 164292 KiB
test_0101.txt AC 1689 ms 162708 KiB
test_0102.txt AC 1673 ms 167548 KiB
test_0103.txt AC 1731 ms 175608 KiB
test_0104.txt AC 1637 ms 158396 KiB
test_0105.txt AC 1706 ms 166588 KiB
test_0106.txt AC 1750 ms 172420 KiB
test_0107.txt AC 1713 ms 169040 KiB
test_0108.txt AC 1689 ms 162308 KiB
test_0109.txt AC 1651 ms 167232 KiB
test_0110.txt AC 1700 ms 165716 KiB
test_0111.txt AC 1766 ms 173432 KiB
test_0112.txt AC 1714 ms 165700 KiB
test_0113.txt AC 1669 ms 162104 KiB
test_0114.txt AC 1794 ms 178068 KiB
test_0115.txt AC 1658 ms 158800 KiB
test_0116.txt AC 1719 ms 159444 KiB
test_0117.txt AC 1663 ms 163980 KiB
test_0118.txt AC 1690 ms 163816 KiB
test_0119.txt AC 1686 ms 163844 KiB
test_0120.txt AC 1744 ms 168640 KiB
test_0121.txt AC 1728 ms 165580 KiB
test_0122.txt AC 1689 ms 159828 KiB
test_0123.txt AC 1681 ms 163004 KiB
test_0124.txt AC 1692 ms 165208 KiB
test_0125.txt AC 1739 ms 170036 KiB
test_0126.txt AC 1667 ms 160244 KiB
test_0127.txt AC 1658 ms 163320 KiB
test_0128.txt AC 1657 ms 162080 KiB
test_0129.txt AC 1719 ms 169860 KiB
test_0130.txt AC 1726 ms 160956 KiB
test_0131.txt AC 1640 ms 159960 KiB
test_0132.txt AC 1730 ms 173772 KiB
test_0133.txt AC 1670 ms 162760 KiB
test_0134.txt AC 1687 ms 166512 KiB
test_0135.txt AC 1708 ms 165264 KiB
test_0136.txt AC 1627 ms 157156 KiB
test_0137.txt AC 1735 ms 170420 KiB
test_0138.txt AC 1698 ms 163956 KiB
test_0139.txt AC 1666 ms 161672 KiB
test_0140.txt AC 1651 ms 157992 KiB
test_0141.txt AC 1774 ms 172468 KiB
test_0142.txt AC 1711 ms 163404 KiB
test_0143.txt AC 1721 ms 163052 KiB
test_0144.txt AC 1757 ms 168344 KiB
test_0145.txt AC 1598 ms 161448 KiB
test_0146.txt AC 1750 ms 170072 KiB
test_0147.txt AC 1732 ms 163620 KiB
test_0148.txt AC 1703 ms 169532 KiB
test_0149.txt AC 1576 ms 150372 KiB