Submission #68843067


Source Code Expand

use std::collections::*;
use std::io::{Write, BufWriter, Read};
// https://qiita.com/tanakh/items/0ba42c7ca36cd29d0ac8
macro_rules! input {
    ($s:expr, $($r:tt)*) => {
        let mut bytes = $s.bytes();
        let mut next = move || -> String{
            bytes.by_ref().map(|r|r as char)
                .skip_while(|c|c.is_whitespace())
                .take_while(|c|!c.is_whitespace())
                .collect()
        };
        input_inner!{next, $($r)*}
    };
}

macro_rules! input_inner {
    ($next:expr) => {};
    ($next:expr,) => {};
    ($next:expr, $var:ident : $t:tt $($r:tt)*) => {
        let $var = read_value!($next, $t);
        input_inner!{$next $($r)*}
    };
}

macro_rules! read_value {
    ($next:expr, ( $($t:tt),* )) => { ($(read_value!($next, $t)),*) };
    ($next:expr, [ $t:tt ; $len:expr ]) => {
        (0..$len).map(|_| read_value!($next, $t)).collect::<Vec<_>>()
    };
    ($next:expr, chars) => {
        read_value!($next, String).chars().collect::<Vec<char>>()
    };
    ($next:expr, $t:ty) => ($next().parse::<$t>().expect("Parse error"));
}

struct Rng {
    x: u64,
}

impl Rng {
    fn next(&mut self) -> u32 {
        let a = 0xdead_c0de_0013_3331u64;
        let b = 2457;
        self.x = self.x.wrapping_mul(a).wrapping_add(b);
        let x = self.x;
        ((x ^ x << 10) >> 32) as _
    }
}

#[allow(unused)]
trait Change { fn chmax(&mut self, x: Self); fn chmin(&mut self, x: Self); }
impl<T: PartialOrd> Change for T {
    fn chmax(&mut self, x: T) { if *self < x { *self = x; } }
    fn chmin(&mut self, x: T) { if *self > x { *self = x; } }
}

fn try_move(
    x: usize, y: usize,
    v: &[Vec<char>], h: &[Vec<char>], dir: char,
) -> Option<(usize, usize)> {
    let n = 30;
    let (nx, ny) = match dir {
        'U' => (x.wrapping_sub(1), y),
        'D' => (x.wrapping_add(1), y),
        'L' => (x, y.wrapping_sub(1)),
        'R' => (x, y.wrapping_add(1)),
        'S' => (x, y),
        _ => unreachable!(),
    };
    if nx >= n || ny >= n {
        return None;
    }
    let is_blocked = match dir {
        'U' => h[nx][y] == '1',
        'D' => h[x][y] == '1',
        'L' => v[x][ny] == '1',
        'R' => v[x][y] == '1',
        'S' => false,
        _ => panic!(),
    };
    if is_blocked {
        None
    } else {
        Some((nx, ny))
    }
}

fn calc_bitboard(
    ij: &[(usize, usize)], v: &[Vec<char>], h: &[Vec<char>],
    alloc: &[Vec<char>], ops: &[usize],
) -> (Vec<u32>, Vec<(usize, usize)>) {
    let n = 30;
    let mut bitboard = vec![0; n];
    let mut pts = vec![];
    for (i, row) in alloc.iter().enumerate() {
        let (mut x, mut y) = ij[i];
        for &o in ops {
            bitboard[x] |= 1 << y;
            let letter = row[o];
            if let Some((nx, ny)) = try_move(x, y, v, h, letter) {
                x = nx;
                y = ny;
            }
        }
        bitboard[x] |= 1 << y;
        pts.push((x, y));
    }
    (bitboard, pts)
}

fn calc_distance(
    v: &[Vec<char>], h: &[Vec<char>],
    bitboard: &[u32],
    que: &mut VecDeque<(i32, usize, usize)>,
) -> Vec<Vec<i32>> {
    let n = 30;
    let mut dist = vec![vec![1000; n]; n];
    for i in 0..n {
        for j in 0..n {
            if (bitboard[i] >> j) & 1 == 0 {
                let mut pushing = false;
                if i > 0 && (bitboard[i - 1] >> j) & 1 == 1 {
                    pushing = true;
                }
                if i + 1 < n && (bitboard[i + 1] >> j) & 1 == 1 {
                    pushing = true;
                }
                if (bitboard[i] >> j) & 3 != 0 {
                    pushing = true;
                }
                if j > 0 && (bitboard[i] >> (j - 1)) & 1 == 1 {
                    pushing = true;
                }
                if pushing {
                    que.push_back((0, i, j));
                } else {
                    dist[i][j] = 0;
                }
            }
        }
    }
    while let Some((d, x, y)) = que.pop_front() {
        if dist[x][y] <= d {
            continue;
        }
        dist[x][y] = d;
        for &(nx, ny) in &[(x.wrapping_sub(1), y), (x + 1, y), (x, y.wrapping_sub(1)), (x, y + 1)] {
            if nx >= n || ny >= n {
                continue;
            }
            let is_blocked = if nx < x {
                h[nx][y] == '1'
            } else if nx > x {
                h[x][y] == '1'
            } else if ny < y {
                v[x][ny] == '1'
            } else {
                v[x][y] == '1'
            };
            if !is_blocked && dist[nx][ny] > d + 1 {
                que.push_back((d + 1, nx, ny));
            }
        }
    }
    dist
}

fn try_once(
    n: usize, m: usize, k: usize,
    ij: &[(usize, usize)],
    v: &[Vec<char>],
    h: &[Vec<char>],
    rng: &mut Rng,
    cutoff: u32,
) -> (u32, Vec<Vec<char>>, Vec<usize>) {
    let mut alloc = vec![vec!['D'; k]; m];
    for i in 0..m {
        for j in 0..10 {
            alloc[i][j] = b"UDLR"[j % 4] as char;
        }
        for j in 1..k {
            let r = rng.next() as usize % (j + 1);
            alloc[i].swap(r, j);
        }
    }
    try_once_with_alloc(n, m, k, ij, v, h, &alloc, cutoff)
}

fn try_once_with_alloc(
    n: usize, m: usize, k: usize,
    ij: &[(usize, usize)],
    v: &[Vec<char>],
    h: &[Vec<char>],
    alloc: &[Vec<char>],
    cutoff: u32,
) -> (u32, Vec<Vec<char>>, Vec<usize>) {
    let max_turns = 3 * n * n - cutoff as usize;
    let mut ops = vec![];
    let mut que = VecDeque::new();
    for _ in 0..max_turns {
        let (now_bb, now_pts) = calc_bitboard(ij, v, h, &alloc, &ops);
        if (0..n).all(|x| now_bb[x] == (1 << n) - 1) {
            break;
        }
        let dist = calc_distance(v, h, &now_bb, &mut que);
        let mut best = (vec![1 << 30], 0);
        for i in 0..k {
            let mut sum = vec![];
            for j in 0..m {
                let np = try_move(now_pts[j].0, now_pts[j].1, v, h, alloc[j][i]);
                let np = np.unwrap_or(now_pts[j]);
                sum.push(dist[np.0][np.1]);
            }
            sum.sort_unstable();
            best = best.min((sum, i));
        }
        ops.push(best.1);
    }
    let (bitboard, _) = calc_bitboard(ij, v, h, &alloc, &ops);
    let mut score = 0;
    for i in 0..n {
        score += bitboard[i].count_ones();
    }
    if score as usize == n * n {
        score = (3 * n * n - ops.len()) as u32;
    }
    (score, alloc.to_vec(), ops)
}

fn main() {
    let out = std::io::stdout();
    let mut out = BufWriter::new(out.lock());
    macro_rules! puts {($($format:tt)*) => (let _ = write!(out,$($format)*););}
    macro_rules! putvec {
        ($v:expr) => {
            for i in 0..$v.len() {
                puts!("{}{}", $v[i], if i + 1 == $v.len() {"\n"} else {" "});
            }
        }
    }
    let args: Vec<_> = std::env::args().collect();
    let istream = if args.len() >= 2 {
        std::fs::read_to_string(&args[1]).unwrap()
    } else {
        std::io::Read::by_ref(&mut std::io::stdin()).bytes().map(|b| b.unwrap() as char).collect()
    };
    input! {
        istream,
        n: usize, m: usize, k: usize,
        ij: [(usize, usize); m],
        v: [chars; n],
        h: [chars; n - 1],
    }
    let mut rng = Rng { x: 0xdead_c0de_0013_3331u64 };
    let mut best_score = 0;
    let mut best_alloc = vec![vec!['D'; k]; m];
    let mut best_ops = vec![];
    for _ in 0..50 {
        let (score, alloc, ops) = try_once(n, m, k, &ij, &v, &h, &mut rng, best_score);
        if score > best_score {
            eprintln!("start: {best_score} -> {score}");
            best_score = score;
            best_alloc = alloc;
            best_ops = ops;
        }
    }
    for _ in 0..138 {
        let mut alloc = best_alloc.to_vec();
        let idx = rng.next() as usize % m;
        let x = rng.next() as usize % k;
        let y = rng.next() as usize % (k - 1) + 1;
        let y = (x + y) % k;
        alloc[idx].swap(x, y);
        let idx = idx + (rng.next() as usize % (m - 1)) + 1;
        let idx = idx % m;
        alloc[idx].swap(x, y);
        let (score, alloc, ops) = try_once_with_alloc(n, m, k, &ij, &v, &h, &alloc, best_score);
        if score > best_score {
            eprintln!("climb: {best_score} -> {score}");
            best_score = score;
            best_alloc = alloc;
            best_ops = ops;
        }
    }
    eprintln!("score = {best_score}");
    // emit ans
    for i in 0..k {
        let mut tmp = vec![];
        for j in 0..m {
            tmp.push(best_alloc[j][i]);
        }
        putvec!(tmp);
    }
    for o in best_ops {
        puts!("{o}\n");
    }
}

Submission Info

Submission Time
Task A - Single Controller Multiple Robots
User kobae964
Language Rust (rustc 1.70.0)
Score 367867
Code Size 8943 Byte
Status AC
Exec Time 2000 ms
Memory 2516 KiB

Judge Result

Set Name test_ALL
Score / Max Score 367867 / 405000
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 1538 ms 2184 KiB
test_0001.txt AC 1569 ms 2260 KiB
test_0002.txt AC 1509 ms 2260 KiB
test_0003.txt AC 1531 ms 2264 KiB
test_0004.txt AC 1438 ms 2192 KiB
test_0005.txt AC 1494 ms 2160 KiB
test_0006.txt AC 1559 ms 2204 KiB
test_0007.txt AC 1497 ms 2176 KiB
test_0008.txt AC 1622 ms 2456 KiB
test_0009.txt AC 1488 ms 2180 KiB
test_0010.txt AC 1855 ms 2136 KiB
test_0011.txt AC 2000 ms 2084 KiB
test_0012.txt AC 1452 ms 2076 KiB
test_0013.txt AC 1528 ms 2292 KiB
test_0014.txt AC 1548 ms 2220 KiB
test_0015.txt AC 1347 ms 2144 KiB
test_0016.txt AC 1545 ms 2384 KiB
test_0017.txt AC 1496 ms 2244 KiB
test_0018.txt AC 1535 ms 2212 KiB
test_0019.txt AC 1482 ms 2108 KiB
test_0020.txt AC 1484 ms 2204 KiB
test_0021.txt AC 1628 ms 2268 KiB
test_0022.txt AC 1493 ms 2224 KiB
test_0023.txt AC 1425 ms 2104 KiB
test_0024.txt AC 1651 ms 2224 KiB
test_0025.txt AC 1583 ms 2352 KiB
test_0026.txt AC 1605 ms 2148 KiB
test_0027.txt AC 1526 ms 2216 KiB
test_0028.txt AC 1532 ms 2252 KiB
test_0029.txt AC 1510 ms 2160 KiB
test_0030.txt AC 1495 ms 2340 KiB
test_0031.txt AC 1563 ms 2180 KiB
test_0032.txt AC 1560 ms 2364 KiB
test_0033.txt AC 1608 ms 2204 KiB
test_0034.txt AC 1453 ms 2288 KiB
test_0035.txt AC 1484 ms 2104 KiB
test_0036.txt AC 1501 ms 2208 KiB
test_0037.txt AC 1667 ms 2192 KiB
test_0038.txt AC 1448 ms 2228 KiB
test_0039.txt AC 1564 ms 2356 KiB
test_0040.txt AC 1553 ms 2200 KiB
test_0041.txt AC 1512 ms 2284 KiB
test_0042.txt AC 1536 ms 2076 KiB
test_0043.txt AC 1463 ms 2220 KiB
test_0044.txt AC 1528 ms 2076 KiB
test_0045.txt AC 1549 ms 2136 KiB
test_0046.txt AC 1562 ms 2384 KiB
test_0047.txt AC 1451 ms 2152 KiB
test_0048.txt AC 1596 ms 2200 KiB
test_0049.txt AC 1458 ms 2264 KiB
test_0050.txt AC 1520 ms 2180 KiB
test_0051.txt AC 1535 ms 2220 KiB
test_0052.txt AC 1542 ms 2256 KiB
test_0053.txt AC 1550 ms 2324 KiB
test_0054.txt AC 1533 ms 2204 KiB
test_0055.txt AC 1488 ms 2244 KiB
test_0056.txt AC 1569 ms 2352 KiB
test_0057.txt AC 1560 ms 2176 KiB
test_0058.txt AC 1638 ms 2200 KiB
test_0059.txt AC 1560 ms 2232 KiB
test_0060.txt AC 1598 ms 2228 KiB
test_0061.txt AC 1548 ms 2364 KiB
test_0062.txt AC 1611 ms 2332 KiB
test_0063.txt AC 1608 ms 2264 KiB
test_0064.txt AC 1574 ms 2292 KiB
test_0065.txt AC 1676 ms 2376 KiB
test_0066.txt AC 1625 ms 2120 KiB
test_0067.txt AC 1457 ms 2152 KiB
test_0068.txt AC 1573 ms 2220 KiB
test_0069.txt AC 1384 ms 2208 KiB
test_0070.txt AC 1587 ms 2376 KiB
test_0071.txt AC 1738 ms 2216 KiB
test_0072.txt AC 1520 ms 2220 KiB
test_0073.txt AC 1712 ms 2292 KiB
test_0074.txt AC 1523 ms 2220 KiB
test_0075.txt AC 1529 ms 2140 KiB
test_0076.txt AC 1579 ms 2368 KiB
test_0077.txt AC 1531 ms 2136 KiB
test_0078.txt AC 1646 ms 2200 KiB
test_0079.txt AC 1568 ms 2208 KiB
test_0080.txt AC 1547 ms 2228 KiB
test_0081.txt AC 1575 ms 2140 KiB
test_0082.txt AC 1501 ms 2164 KiB
test_0083.txt AC 1524 ms 2444 KiB
test_0084.txt AC 1450 ms 2152 KiB
test_0085.txt AC 1711 ms 2252 KiB
test_0086.txt AC 1409 ms 2228 KiB
test_0087.txt AC 1554 ms 2068 KiB
test_0088.txt AC 1466 ms 2164 KiB
test_0089.txt AC 1777 ms 2216 KiB
test_0090.txt AC 1494 ms 2204 KiB
test_0091.txt AC 1494 ms 2212 KiB
test_0092.txt AC 1452 ms 2308 KiB
test_0093.txt AC 1537 ms 2212 KiB
test_0094.txt AC 1504 ms 2232 KiB
test_0095.txt AC 1579 ms 2140 KiB
test_0096.txt AC 1715 ms 2344 KiB
test_0097.txt AC 1526 ms 2216 KiB
test_0098.txt AC 1680 ms 2140 KiB
test_0099.txt AC 1534 ms 2088 KiB
test_0100.txt AC 1469 ms 2184 KiB
test_0101.txt AC 1645 ms 2216 KiB
test_0102.txt AC 1648 ms 2288 KiB
test_0103.txt AC 1509 ms 2376 KiB
test_0104.txt AC 1404 ms 2264 KiB
test_0105.txt AC 1551 ms 2320 KiB
test_0106.txt AC 1469 ms 2200 KiB
test_0107.txt AC 1585 ms 2220 KiB
test_0108.txt AC 1483 ms 2208 KiB
test_0109.txt AC 1552 ms 2076 KiB
test_0110.txt AC 1565 ms 2164 KiB
test_0111.txt AC 1651 ms 2516 KiB
test_0112.txt AC 1603 ms 2084 KiB
test_0113.txt AC 1484 ms 2224 KiB
test_0114.txt AC 1488 ms 2188 KiB
test_0115.txt AC 1619 ms 2072 KiB
test_0116.txt AC 1604 ms 2084 KiB
test_0117.txt AC 1397 ms 2152 KiB
test_0118.txt AC 1521 ms 2156 KiB
test_0119.txt AC 1608 ms 2368 KiB
test_0120.txt AC 1589 ms 2364 KiB
test_0121.txt AC 1496 ms 2120 KiB
test_0122.txt AC 1505 ms 2164 KiB
test_0123.txt AC 1525 ms 2260 KiB
test_0124.txt AC 1449 ms 2184 KiB
test_0125.txt AC 1523 ms 2172 KiB
test_0126.txt AC 1601 ms 2288 KiB
test_0127.txt AC 1679 ms 2216 KiB
test_0128.txt AC 1569 ms 2216 KiB
test_0129.txt AC 1456 ms 2220 KiB
test_0130.txt AC 1436 ms 2200 KiB
test_0131.txt AC 1432 ms 2108 KiB
test_0132.txt AC 1587 ms 2344 KiB
test_0133.txt AC 1479 ms 2248 KiB
test_0134.txt AC 1581 ms 2116 KiB
test_0135.txt AC 1379 ms 2296 KiB
test_0136.txt AC 1576 ms 2184 KiB
test_0137.txt AC 1597 ms 2116 KiB
test_0138.txt AC 1556 ms 2264 KiB
test_0139.txt AC 1542 ms 2188 KiB
test_0140.txt AC 1476 ms 2200 KiB
test_0141.txt AC 1503 ms 2228 KiB
test_0142.txt AC 1548 ms 2160 KiB
test_0143.txt AC 1698 ms 2016 KiB
test_0144.txt AC 1486 ms 2220 KiB
test_0145.txt AC 1539 ms 2140 KiB
test_0146.txt AC 1478 ms 2224 KiB
test_0147.txt AC 1519 ms 2196 KiB
test_0148.txt AC 1541 ms 2156 KiB
test_0149.txt AC 1544 ms 2184 KiB