提出 #73751556
ソースコード 拡げる
use std::io::{self, Read};
use std::str::FromStr;
use std::collections::HashMap;
struct Scanner {
buf: Vec<u8>,
idx: usize,
}
impl Scanner {
fn new() -> Self {
let mut input = String::new();
io::stdin().read_to_string(&mut input).unwrap();
Self {
buf: input.into_bytes(),
idx: 0,
}
}
fn next<T: FromStr>(&mut self) -> T {
while self.idx < self.buf.len() && self.buf[self.idx].is_ascii_whitespace() {
self.idx += 1;
}
let start = self.idx;
while self.idx < self.buf.len() && !self.buf[self.idx].is_ascii_whitespace() {
self.idx += 1;
}
std::str::from_utf8(&self.buf[start..self.idx])
.unwrap()
.parse::<T>()
.ok()
.unwrap()
}
}
#[derive(Clone)]
struct RobotPlan {
i: usize,
j: usize,
d: char,
trans: Vec<(char, usize, char, usize)>,
}
impl RobotPlan {
fn m(&self) -> usize {
self.trans.len()
}
}
#[derive(Clone)]
struct Candidate {
cost: usize,
mask: Vec<u64>,
robot: RobotPlan,
}
fn set_bit(mask: &mut [u64], idx: usize) {
mask[idx >> 6] |= 1_u64 << (idx & 63);
}
fn count_intersection(a: &[u64], b: &[u64]) -> usize {
a.iter()
.zip(b.iter())
.map(|(&x, &y)| (x & y).count_ones() as usize)
.sum()
}
fn any_bit(mask: &[u64]) -> bool {
mask.iter().any(|&x| x != 0)
}
fn for_each_bit(mask: &[u64], mut f: impl FnMut(usize)) {
for (w, &bits0) in mask.iter().enumerate() {
let mut bits = bits0;
while bits != 0 {
let t = bits.trailing_zeros() as usize;
f((w << 6) + t);
bits &= bits - 1;
}
}
}
fn splitmix64(mut x: u64) -> u64 {
x = x.wrapping_add(0x9e3779b97f4a7c15);
x = (x ^ (x >> 30)).wrapping_mul(0xbf58476d1ce4e5b9);
x = (x ^ (x >> 27)).wrapping_mul(0x94d049bb133111eb);
x ^ (x >> 31)
}
fn next_rand(state: &mut u64) -> u64 {
*state = splitmix64(*state);
*state
}
fn env_usize(name: &str, default: usize) -> usize {
std::env::var(name)
.ok()
.and_then(|s| s.parse::<usize>().ok())
.unwrap_or(default)
}
fn mask_popcount(mask: &[u64]) -> usize {
mask.iter().map(|&x| x.count_ones() as usize).sum()
}
fn dir_char(d: usize) -> char {
match d {
0 => 'U',
1 => 'R',
2 => 'D',
_ => 'L',
}
}
fn front_blocked(n: usize, v: &[Vec<u8>], h: &[Vec<u8>], i: usize, j: usize, d: usize) -> bool {
match d {
0 => i == 0 || h[i - 1][j] == 1, // U
1 => j == n - 1 || v[i][j] == 1, // R
2 => i == n - 1 || h[i][j] == 1, // D
_ => j == 0 || v[i][j - 1] == 1, // L
}
}
fn apply_action(i: usize, j: usize, d: usize, a: char) -> (usize, usize, usize) {
match a {
'R' => (i, j, (d + 1) & 3),
'L' => (i, j, (d + 3) & 3),
'F' => match d {
0 => (i - 1, j, d),
1 => (i, j + 1, d),
2 => (i + 1, j, d),
_ => (i, j - 1, d),
},
_ => unreachable!(),
}
}
fn generate_one_state_candidates(
n: usize,
v: &[Vec<u8>],
h: &[Vec<u8>],
words: usize,
) -> Vec<Candidate> {
let options = [('F', 'R'), ('F', 'L'), ('R', 'R'), ('R', 'L'), ('L', 'R'), ('L', 'L')];
let s = n * n * 4;
let mut out = Vec::new();
for &(a0, a1) in &options {
let mut next = vec![0usize; s];
for node in 0..s {
let cell = node >> 2;
let d = node & 3;
let i = cell / n;
let j = cell % n;
let blocked = front_blocked(n, v, h, i, j, d);
let action = if blocked { a1 } else { a0 };
let (ni, nj, nd) = apply_action(i, j, d, action);
next[node] = (((ni * n) + nj) << 2) | nd;
}
let mut node_cycle = vec![usize::MAX; s];
let mut pos = vec![usize::MAX; s];
let mut cycle_masks: Vec<Vec<u64>> = Vec::new();
let mut cycle_rep: Vec<usize> = Vec::new();
for start in 0..s {
if node_cycle[start] != usize::MAX {
continue;
}
let mut stack: Vec<usize> = Vec::new();
let mut cur = start;
while node_cycle[cur] == usize::MAX && pos[cur] == usize::MAX {
pos[cur] = stack.len();
stack.push(cur);
cur = next[cur];
}
if node_cycle[cur] != usize::MAX {
let cid = node_cycle[cur];
for &u in stack.iter().rev() {
node_cycle[u] = cid;
}
} else {
let p = pos[cur];
let cycle_nodes = &stack[p..];
let mut mask = vec![0_u64; words];
for &u in cycle_nodes {
set_bit(&mut mask, u >> 2);
}
let cid = cycle_masks.len();
cycle_masks.push(mask);
cycle_rep.push(cycle_nodes[0]);
for &u in cycle_nodes {
node_cycle[u] = cid;
}
for &u in stack[..p].iter().rev() {
node_cycle[u] = cid;
}
}
for &u in &stack {
pos[u] = usize::MAX;
}
}
for cid in 0..cycle_masks.len() {
let rep = cycle_rep[cid];
let cell = rep >> 2;
let d = rep & 3;
let i = cell / n;
let j = cell % n;
out.push(Candidate {
cost: 1,
mask: cycle_masks[cid].clone(),
robot: RobotPlan {
i,
j,
d: dir_char(d),
trans: vec![(a0, 0, a1, 0)],
},
});
}
}
out
}
fn generate_row_segment_candidates(n: usize, v: &[Vec<u8>], words: usize) -> Vec<Candidate> {
let mut out = Vec::new();
for i in 0..n {
let mut j = 0usize;
while j < n {
let start = j;
let mut mask = vec![0_u64; words];
set_bit(&mut mask, i * n + j);
while j + 1 < n && v[i][j] == 0 {
j += 1;
set_bit(&mut mask, i * n + j);
}
out.push(Candidate {
cost: 2,
mask,
robot: RobotPlan {
i,
j: start,
d: 'R',
trans: vec![('F', 0, 'R', 1), ('R', 0, 'R', 0)],
},
});
j += 1;
}
}
out
}
fn generate_col_segment_candidates(n: usize, h: &[Vec<u8>], words: usize) -> Vec<Candidate> {
let mut out = Vec::new();
for j in 0..n {
let mut i = 0usize;
while i < n {
let start = i;
let mut mask = vec![0_u64; words];
set_bit(&mut mask, i * n + j);
while i + 1 < n && h[i][j] == 0 {
i += 1;
set_bit(&mut mask, i * n + j);
}
out.push(Candidate {
cost: 2,
mask,
robot: RobotPlan {
i: start,
j,
d: 'D',
trans: vec![('F', 0, 'R', 1), ('R', 0, 'R', 0)],
},
});
i += 1;
}
}
out
}
fn generate_two_state_candidates(
n: usize,
v: &[Vec<u8>],
h: &[Vec<u8>],
words: usize,
) -> Vec<Candidate> {
let cells = n * n;
let s = cells * 4 * 2;
let a0s = ['F', 'R', 'L'];
let a1s = ['R', 'L'];
let mut state_cfgs = Vec::new();
for &a0 in &a0s {
for b0 in 0..2 {
for &a1 in &a1s {
for b1 in 0..2 {
state_cfgs.push((a0, b0, a1, b1));
}
}
}
}
let mut out = Vec::new();
for &c0 in &state_cfgs {
for &c1 in &state_cfgs {
let trans = [c0, c1];
let mut next = vec![0usize; s];
for node in 0..s {
let st = node & 1;
let dir = (node >> 1) & 3;
let cell = node >> 3;
let i = cell / n;
let j = cell % n;
let wall = front_blocked(n, v, h, i, j, dir);
let (a, b) = if !wall {
(trans[st].0, trans[st].1)
} else {
(trans[st].2, trans[st].3)
};
let (ni, nj, nd) = apply_action(i, j, dir, a);
next[node] = ((((ni * n + nj) << 2) | nd) << 1) | b;
}
let mut node_cycle = vec![usize::MAX; s];
let mut pos = vec![usize::MAX; s];
let mut cycle_masks: Vec<Vec<u64>> = Vec::new();
let mut rep_start: Vec<usize> = Vec::new();
for start in 0..s {
if node_cycle[start] != usize::MAX {
continue;
}
let mut stack = Vec::new();
let mut cur = start;
while node_cycle[cur] == usize::MAX && pos[cur] == usize::MAX {
pos[cur] = stack.len();
stack.push(cur);
cur = next[cur];
}
if node_cycle[cur] != usize::MAX {
let cid = node_cycle[cur];
for &u in stack.iter().rev() {
node_cycle[u] = cid;
}
} else {
let p = pos[cur];
let mut mask = vec![0_u64; words];
for &u in &stack[p..] {
set_bit(&mut mask, u >> 3);
}
let cid = cycle_masks.len();
cycle_masks.push(mask);
rep_start.push(usize::MAX);
for &u in &stack[p..] {
node_cycle[u] = cid;
}
for &u in stack[..p].iter().rev() {
node_cycle[u] = cid;
}
}
for &u in &stack {
pos[u] = usize::MAX;
}
}
for cell in 0..cells {
for d in 0..4 {
let node = ((cell << 2) | d) << 1; // internal state = 0
let cid = node_cycle[node];
if rep_start[cid] == usize::MAX {
rep_start[cid] = node;
}
}
}
for (cid, &node) in rep_start.iter().enumerate() {
if node == usize::MAX {
continue;
}
let cell = node >> 3;
let d = (node >> 1) & 3;
let i = cell / n;
let j = cell % n;
out.push(Candidate {
cost: 2,
mask: cycle_masks[cid].clone(),
robot: RobotPlan {
i,
j,
d: dir_char(d),
trans: vec![
(trans[0].0, trans[0].1, trans[0].2, trans[0].3),
(trans[1].0, trans[1].1, trans[1].2, trans[1].3),
],
},
});
}
}
}
out
}
fn generate_random_m_state_candidates(
n: usize,
v: &[Vec<u8>],
h: &[Vec<u8>],
words: usize,
m: usize,
automata_count: usize,
picks_per_automaton: usize,
seed: u64,
) -> Vec<Candidate> {
let cells = n * n;
let s = cells * 4 * m;
let a0s = ['F', 'R', 'L'];
let a1s = ['R', 'L'];
let mut rng = seed ^ (m as u64).wrapping_mul(0xabc9_8731_55aa_41c7);
let mut out = Vec::new();
for _ in 0..automata_count {
let mut trans = vec![('F', 0usize, 'R', 0usize); m];
let mut has_f = false;
for st in 0..m {
let a0 = a0s[(next_rand(&mut rng) % (a0s.len() as u64)) as usize];
if a0 == 'F' {
has_f = true;
}
let b0 = (next_rand(&mut rng) % (m as u64)) as usize;
let a1 = a1s[(next_rand(&mut rng) % (a1s.len() as u64)) as usize];
let b1 = (next_rand(&mut rng) % (m as u64)) as usize;
trans[st] = (a0, b0, a1, b1);
}
if !has_f {
continue;
}
let mut next = vec![0usize; s];
for node in 0..s {
let st = node % m;
let q = node / m;
let d = q & 3;
let cell = q >> 2;
let i = cell / n;
let j = cell % n;
let wall = front_blocked(n, v, h, i, j, d);
let (a, b) = if !wall {
(trans[st].0, trans[st].1)
} else {
(trans[st].2, trans[st].3)
};
let (ni, nj, nd) = apply_action(i, j, d, a);
next[node] = ((((ni * n + nj) << 2) | nd) * m) + b;
}
let mut node_cycle = vec![usize::MAX; s];
let mut pos = vec![usize::MAX; s];
let mut cycle_masks: Vec<Vec<u64>> = Vec::new();
let mut rep_start: Vec<usize> = Vec::new();
for start in 0..s {
if node_cycle[start] != usize::MAX {
continue;
}
let mut stack = Vec::new();
let mut cur = start;
while node_cycle[cur] == usize::MAX && pos[cur] == usize::MAX {
pos[cur] = stack.len();
stack.push(cur);
cur = next[cur];
}
if node_cycle[cur] != usize::MAX {
let cid = node_cycle[cur];
for &u in stack.iter().rev() {
node_cycle[u] = cid;
}
} else {
let p = pos[cur];
let mut mask = vec![0_u64; words];
for &u in &stack[p..] {
set_bit(&mut mask, (u / m) >> 2);
}
let cid = cycle_masks.len();
cycle_masks.push(mask);
rep_start.push(usize::MAX);
for &u in &stack[p..] {
node_cycle[u] = cid;
}
for &u in stack[..p].iter().rev() {
node_cycle[u] = cid;
}
}
for &u in &stack {
pos[u] = usize::MAX;
}
}
for cell in 0..cells {
for d in 0..4 {
let node = (((cell << 2) | d) * m) + 0;
let cid = node_cycle[node];
if rep_start[cid] == usize::MAX {
rep_start[cid] = node;
}
}
}
let mut picks = Vec::new();
for (cid, &node) in rep_start.iter().enumerate() {
if node == usize::MAX {
continue;
}
let sz = mask_popcount(&cycle_masks[cid]);
picks.push((sz, cid, node));
}
picks.sort_by_key(|&(sz, _, node)| (std::cmp::Reverse(sz), node));
picks.truncate(picks_per_automaton);
for (_, cid, node) in picks {
let cell = (node / m) >> 2;
let d = (node / m) & 3;
let i = cell / n;
let j = cell % n;
out.push(Candidate {
cost: m,
mask: cycle_masks[cid].clone(),
robot: RobotPlan {
i,
j,
d: dir_char(d),
trans: trans.clone(),
},
});
}
}
out
}
fn build_candidate_cells(candidates: &[Candidate], cells: usize) -> Vec<Vec<usize>> {
let mut out = Vec::with_capacity(candidates.len());
for c in candidates {
let mut v = Vec::new();
for_each_bit(&c.mask, |p| {
if p < cells {
v.push(p);
}
});
out.push(v);
}
out
}
fn improve_by_add_remove(
candidates: &[Candidate],
cand_cells: &[Vec<usize>],
mut selected: Vec<usize>,
cells: usize,
) -> Vec<usize> {
let n = candidates.len();
let mut sel = vec![false; n];
for &idx in &selected {
sel[idx] = true;
}
let mut cnt = vec![0_u16; cells];
for &idx in &selected {
for &p in &cand_cells[idx] {
cnt[p] += 1;
}
}
let mut order: Vec<usize> = (0..n).collect();
order.sort_by_key(|&idx| std::cmp::Reverse(candidates[idx].cost));
for it in 0..4 {
let mut best_add = usize::MAX;
let mut best_removed: Vec<usize> = Vec::new();
let mut best_delta = 0_i32;
let mut add_order: Vec<usize> = (0..n).filter(|&idx| !sel[idx]).collect();
add_order.sort_by_key(|&idx| splitmix64((it as u64) ^ ((idx as u64) * 0x9e3779b97f4a7c15)));
for &add_idx in add_order.iter().take(1024) {
if sel[add_idx] {
continue;
}
let mut cnt2 = cnt.clone();
for &p in &cand_cells[add_idx] {
cnt2[p] += 1;
}
let mut removed = Vec::new();
let mut removed_cost = 0_i32;
for &idx in &order {
if !sel[idx] {
continue;
}
let mut ok = true;
for &p in &cand_cells[idx] {
if cnt2[p] <= 1 {
ok = false;
break;
}
}
if ok {
for &p in &cand_cells[idx] {
cnt2[p] -= 1;
}
removed.push(idx);
removed_cost += candidates[idx].cost as i32;
}
}
let delta = candidates[add_idx].cost as i32 - removed_cost;
if delta < best_delta {
best_delta = delta;
best_add = add_idx;
best_removed = removed;
}
}
if best_add == usize::MAX {
break;
}
sel[best_add] = true;
for &p in &cand_cells[best_add] {
cnt[p] += 1;
}
selected.push(best_add);
for &idx in &best_removed {
if !sel[idx] {
continue;
}
sel[idx] = false;
for &p in &cand_cells[idx] {
cnt[p] -= 1;
}
}
selected.retain(|&idx| sel[idx]);
}
selected
}
fn improve_by_drop_repair(
candidates: &[Candidate],
cand_cells: &[Vec<usize>],
selected: Vec<usize>,
cells: usize,
seed: u64,
passes: usize,
) -> Vec<usize> {
let n = candidates.len();
let mut sel = vec![false; n];
for &idx in &selected {
sel[idx] = true;
}
let mut cnt = vec![0_u16; cells];
let mut cost: i32 = 0;
for &idx in &selected {
cost += candidates[idx].cost as i32;
for &p in &cand_cells[idx] {
cnt[p] += 1;
}
}
for pass in 0..(passes as u64) {
let mut sel_list: Vec<usize> = (0..n).filter(|&idx| sel[idx]).collect();
sel_list.sort_by_key(|&idx| {
(
std::cmp::Reverse(candidates[idx].cost),
splitmix64(seed ^ pass ^ ((idx as u64) * 0x9e3779b97f4a7c15)),
)
});
let mut improved = false;
for rm in sel_list {
let mut lsel = sel.clone();
let mut lcnt = cnt.clone();
let mut lcost = cost;
lsel[rm] = false;
lcost -= candidates[rm].cost as i32;
for &p in &cand_cells[rm] {
lcnt[p] -= 1;
}
let mut uncovered = 0usize;
for &x in &lcnt {
if x == 0 {
uncovered += 1;
}
}
if uncovered == 0 && lcost < cost {
sel = lsel;
cnt = lcnt;
cost = lcost;
improved = true;
break;
}
while uncovered > 0 && lcost < cost {
let mut best_idx = usize::MAX;
let mut best_gain = 0usize;
let mut best_cost = 1usize;
let mut best_key = u64::MAX;
for idx in 0..n {
if lsel[idx] {
continue;
}
let mut gain = 0usize;
for &p in &cand_cells[idx] {
if lcnt[p] == 0 {
gain += 1;
}
}
if gain == 0 {
continue;
}
let c = candidates[idx].cost;
let key = splitmix64(seed ^ pass ^ ((idx as u64) * 0xbf58476d1ce4e5b9));
let better = if best_idx == usize::MAX {
true
} else {
let lhs = gain * best_cost;
let rhs = best_gain * c;
lhs > rhs
|| (lhs == rhs
&& (gain > best_gain
|| (gain == best_gain
&& (c < best_cost || (c == best_cost && key < best_key)))))
};
if better {
best_idx = idx;
best_gain = gain;
best_cost = c;
best_key = key;
}
}
if best_idx == usize::MAX {
break;
}
lsel[best_idx] = true;
lcost += candidates[best_idx].cost as i32;
for &p in &cand_cells[best_idx] {
if lcnt[p] == 0 {
uncovered -= 1;
}
lcnt[p] += 1;
}
}
if uncovered == 0 && lcost < cost {
sel = lsel;
cnt = lcnt;
cost = lcost;
improved = true;
break;
}
}
if !improved {
break;
}
}
(0..n).filter(|&idx| sel[idx]).collect()
}
fn dedup_candidates(candidates: Vec<Candidate>) -> Vec<Candidate> {
let mut out: Vec<Candidate> = Vec::new();
let mut pos: HashMap<Vec<u64>, usize> = HashMap::new();
for c in candidates {
if let Some(&idx) = pos.get(&c.mask) {
if c.cost < out[idx].cost {
out[idx] = c;
}
} else {
let idx = out.len();
pos.insert(c.mask.clone(), idx);
out.push(c);
}
}
out
}
fn solve_weighted_cover(candidates: &[Candidate], cells: usize, seed: u64) -> Vec<usize> {
let words = (cells + 63) >> 6;
let mut uncovered = vec![!0_u64; words];
if cells & 63 != 0 {
uncovered[words - 1] = (1_u64 << (cells & 63)) - 1;
}
let mut used = vec![false; candidates.len()];
let mut selected: Vec<usize> = Vec::new();
while any_bit(&uncovered) {
let mut best_idx = usize::MAX;
let mut best_gain = 0usize;
let mut best_cost = 1usize;
let mut best_key = u64::MAX;
for (idx, c) in candidates.iter().enumerate() {
if used[idx] {
continue;
}
let gain = count_intersection(&c.mask, &uncovered);
if gain == 0 {
continue;
}
let better = if best_idx == usize::MAX {
true
} else {
let lhs = gain * best_cost;
let rhs = best_gain * c.cost;
let key = splitmix64(seed ^ (idx as u64).wrapping_mul(0x9e3779b97f4a7c15));
lhs > rhs
|| (lhs == rhs
&& (gain > best_gain
|| (gain == best_gain
&& (c.cost < best_cost
|| (c.cost == best_cost && key < best_key)))))
};
if better {
best_idx = idx;
best_gain = gain;
best_cost = c.cost;
best_key = splitmix64(seed ^ (idx as u64).wrapping_mul(0x9e3779b97f4a7c15));
}
}
if best_idx == usize::MAX {
break;
}
used[best_idx] = true;
selected.push(best_idx);
for (u, &m) in uncovered.iter_mut().zip(candidates[best_idx].mask.iter()) {
*u &= !m;
}
}
let mut cnt = vec![0_u16; cells];
for &idx in &selected {
for_each_bit(&candidates[idx].mask, |p| {
if p < cells {
cnt[p] += 1;
}
});
}
let mut active = vec![true; selected.len()];
loop {
let mut changed = false;
for t in (0..selected.len()).rev() {
if !active[t] {
continue;
}
let idx = selected[t];
let mut removable = true;
for_each_bit(&candidates[idx].mask, |p| {
if p < cells && cnt[p] <= 1 {
removable = false;
}
});
if removable {
active[t] = false;
changed = true;
for_each_bit(&candidates[idx].mask, |p| {
if p < cells {
cnt[p] -= 1;
}
});
}
}
if !changed {
break;
}
}
let mut out = Vec::new();
for (t, &idx) in selected.iter().enumerate() {
if active[t] {
out.push(idx);
}
}
out
}
fn main() {
let mut sc = Scanner::new();
let n: usize = sc.next();
let _ak: i64 = sc.next();
let _am: i64 = sc.next();
let _aw: i64 = sc.next();
let mut v = vec![vec![0_u8; n - 1]; n];
for row in &mut v {
let s: String = sc.next();
for (j, &b) in s.as_bytes().iter().enumerate() {
row[j] = (b == b'1') as u8;
}
}
let mut h = vec![vec![0_u8; n]; n - 1];
for row in &mut h {
let s: String = sc.next();
for (j, &b) in s.as_bytes().iter().enumerate() {
row[j] = (b == b'1') as u8;
}
}
let cells = n * n;
let words = (cells + 63) >> 6;
let mut seed_base = 0x1234_5678_9abc_def0_u64 ^ (n as u64);
for row in &v {
for &x in row {
seed_base = splitmix64(seed_base ^ (x as u64 + 1));
}
}
for row in &h {
for &x in row {
seed_base = splitmix64(seed_base ^ (x as u64 + 3));
}
}
let mut candidates = generate_one_state_candidates(n, &v, &h, words);
let row_candidates = generate_row_segment_candidates(n, &v, words);
let col_candidates = generate_col_segment_candidates(n, &h, words);
let two_state_candidates = generate_two_state_candidates(n, &v, &h, words);
let c3 = env_usize("C3_AUT", 768);
let p3 = env_usize("C3_PICK", 12);
let c4 = env_usize("C4_AUT", 512);
let p4 = env_usize("C4_PICK", 10);
let c5 = env_usize("C5_AUT", 256);
let p5 = env_usize("C5_PICK", 8);
let c6 = env_usize("C6_AUT", 512);
let p6 = env_usize("C6_PICK", 8);
let c7 = env_usize("C7_AUT", 256);
let p7 = env_usize("C7_PICK", 6);
let c8 = env_usize("C8_AUT", 96);
let p8 = env_usize("C8_PICK", 5);
let c9 = env_usize("C9_AUT", 192);
let p9 = env_usize("C9_PICK", 5);
let c12 = env_usize("C12_AUT", 96);
let p12 = env_usize("C12_PICK", 4);
let c15 = env_usize("C15_AUT", 64);
let p15 = env_usize("C15_PICK", 3);
let three_state_candidates =
generate_random_m_state_candidates(n, &v, &h, words, 3, c3, p3, seed_base ^ 0x1357_9bdf);
let four_state_candidates =
generate_random_m_state_candidates(n, &v, &h, words, 4, c4, p4, seed_base ^ 0x2468_ace0);
let five_state_candidates =
generate_random_m_state_candidates(n, &v, &h, words, 5, c5, p5, seed_base ^ 0x3141_5926);
let six_state_candidates =
generate_random_m_state_candidates(n, &v, &h, words, 6, c6, p6, seed_base ^ 0x2718_2818);
let seven_state_candidates =
generate_random_m_state_candidates(n, &v, &h, words, 7, c7, p7, seed_base ^ 0x1618_0339);
let eight_state_candidates =
generate_random_m_state_candidates(n, &v, &h, words, 8, c8, p8, seed_base ^ 0x5772_1566);
let nine_state_candidates =
generate_random_m_state_candidates(n, &v, &h, words, 9, c9, p9, seed_base ^ 0x1414_2135);
let twelve_state_candidates =
generate_random_m_state_candidates(n, &v, &h, words, 12, c12, p12, seed_base ^ 0x1234_4321);
let fifteen_state_candidates =
generate_random_m_state_candidates(n, &v, &h, words, 15, c15, p15, seed_base ^ 0x0f0f_a5a5);
candidates.extend(row_candidates.clone());
candidates.extend(col_candidates.clone());
candidates.extend(two_state_candidates);
candidates.extend(three_state_candidates);
candidates.extend(four_state_candidates);
candidates.extend(five_state_candidates);
candidates.extend(six_state_candidates);
candidates.extend(seven_state_candidates);
candidates.extend(eight_state_candidates);
candidates.extend(nine_state_candidates);
candidates.extend(twelve_state_candidates);
candidates.extend(fifteen_state_candidates);
candidates = dedup_candidates(candidates);
let cand_cells = build_candidate_cells(&candidates, cells);
let mut best_selected = solve_weighted_cover(&candidates, cells, seed_base);
let starts = env_usize("START_TRIALS", 20).max(1);
let drop_passes = env_usize("DROP_PASSES", 4).max(1);
best_selected = improve_by_add_remove(&candidates, &cand_cells, best_selected, cells);
let mut best_m: usize = best_selected.iter().map(|&idx| candidates[idx].cost).sum();
for t in 1_u64..(starts as u64) {
let selected = solve_weighted_cover(&candidates, cells, seed_base ^ splitmix64(t));
let selected = improve_by_add_remove(&candidates, &cand_cells, selected, cells);
let m: usize = selected.iter().map(|&idx| candidates[idx].cost).sum();
if m < best_m {
best_m = m;
best_selected = selected;
}
}
best_selected = improve_by_drop_repair(
&candidates,
&cand_cells,
best_selected,
cells,
seed_base,
drop_passes,
);
let mut robots: Vec<RobotPlan> = best_selected
.iter()
.map(|&idx| candidates[idx].robot.clone())
.collect();
let mut m_sum: usize = robots.iter().map(RobotPlan::m).sum();
let mut row_baseline: Vec<RobotPlan> = row_candidates.iter().map(|c| c.robot.clone()).collect();
let mut col_baseline: Vec<RobotPlan> = col_candidates.iter().map(|c| c.robot.clone()).collect();
let row_m: usize = row_baseline.iter().map(RobotPlan::m).sum();
let col_m: usize = col_baseline.iter().map(RobotPlan::m).sum();
let baseline = if row_m <= col_m {
(&mut row_baseline, row_m)
} else {
(&mut col_baseline, col_m)
};
if m_sum > baseline.1 {
robots = baseline.0.clone();
m_sum = baseline.1;
}
if robots.is_empty() {
robots.push(RobotPlan {
i: 0,
j: 0,
d: 'U',
trans: vec![('R', 0, 'R', 0)],
});
m_sum = 1;
}
let _ = m_sum;
println!("{}", robots.len());
for rb in &robots {
println!("{} {} {} {}", rb.m(), rb.i, rb.j, rb.d);
for &(a0, b0, a1, b1) in &rb.trans {
println!("{} {} {} {}", a0, b0, a1, b1);
}
}
let z1 = "0".repeat(n.saturating_sub(1));
for _ in 0..n {
println!("{}", z1);
}
let z2 = "0".repeat(n);
for _ in 0..n.saturating_sub(1) {
println!("{}", z2);
}
}
提出情報
ジャッジ結果
| セット名 |
test_ALL |
| 得点 / 配点 |
628034695 / 15000000000 |
| 結果 |
|
| セット名 |
テストケース |
| 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 |
| ケース名 |
結果 |
実行時間 |
メモリ |
| test_0000.txt |
AC |
577 ms |
62780 KiB |
| test_0001.txt |
AC |
546 ms |
64056 KiB |
| test_0002.txt |
AC |
577 ms |
63096 KiB |
| test_0003.txt |
AC |
700 ms |
62960 KiB |
| test_0004.txt |
AC |
550 ms |
64044 KiB |
| test_0005.txt |
AC |
602 ms |
65376 KiB |
| test_0006.txt |
AC |
551 ms |
63176 KiB |
| test_0007.txt |
AC |
566 ms |
63264 KiB |
| test_0008.txt |
AC |
684 ms |
63424 KiB |
| test_0009.txt |
AC |
555 ms |
63696 KiB |
| test_0010.txt |
AC |
636 ms |
62928 KiB |
| test_0011.txt |
AC |
543 ms |
64500 KiB |
| test_0012.txt |
AC |
552 ms |
64180 KiB |
| test_0013.txt |
AC |
549 ms |
64256 KiB |
| test_0014.txt |
AC |
558 ms |
65584 KiB |
| test_0015.txt |
AC |
617 ms |
63480 KiB |
| test_0016.txt |
AC |
584 ms |
64312 KiB |
| test_0017.txt |
AC |
615 ms |
64032 KiB |
| test_0018.txt |
AC |
576 ms |
62624 KiB |
| test_0019.txt |
AC |
702 ms |
63532 KiB |
| test_0020.txt |
AC |
590 ms |
65036 KiB |
| test_0021.txt |
AC |
545 ms |
63884 KiB |
| test_0022.txt |
AC |
666 ms |
60812 KiB |
| test_0023.txt |
AC |
547 ms |
64256 KiB |
| test_0024.txt |
AC |
566 ms |
63020 KiB |
| test_0025.txt |
AC |
565 ms |
65132 KiB |
| test_0026.txt |
AC |
701 ms |
64212 KiB |
| test_0027.txt |
AC |
559 ms |
64236 KiB |
| test_0028.txt |
AC |
618 ms |
63572 KiB |
| test_0029.txt |
AC |
558 ms |
64176 KiB |
| test_0030.txt |
AC |
549 ms |
63268 KiB |
| test_0031.txt |
AC |
574 ms |
63296 KiB |
| test_0032.txt |
AC |
538 ms |
64424 KiB |
| test_0033.txt |
AC |
572 ms |
63324 KiB |
| test_0034.txt |
AC |
600 ms |
63464 KiB |
| test_0035.txt |
AC |
596 ms |
62504 KiB |
| test_0036.txt |
AC |
563 ms |
62976 KiB |
| test_0037.txt |
AC |
595 ms |
65604 KiB |
| test_0038.txt |
AC |
580 ms |
63216 KiB |
| test_0039.txt |
AC |
558 ms |
64988 KiB |
| test_0040.txt |
AC |
648 ms |
64460 KiB |
| test_0041.txt |
AC |
546 ms |
65596 KiB |
| test_0042.txt |
AC |
602 ms |
64108 KiB |
| test_0043.txt |
AC |
615 ms |
64516 KiB |
| test_0044.txt |
AC |
574 ms |
64328 KiB |
| test_0045.txt |
AC |
583 ms |
65380 KiB |
| test_0046.txt |
AC |
582 ms |
63208 KiB |
| test_0047.txt |
AC |
558 ms |
64056 KiB |
| test_0048.txt |
AC |
560 ms |
63244 KiB |
| test_0049.txt |
AC |
565 ms |
63104 KiB |
| test_0050.txt |
AC |
579 ms |
62916 KiB |
| test_0051.txt |
AC |
560 ms |
63896 KiB |
| test_0052.txt |
AC |
624 ms |
63568 KiB |
| test_0053.txt |
AC |
551 ms |
64316 KiB |
| test_0054.txt |
AC |
549 ms |
63092 KiB |
| test_0055.txt |
AC |
618 ms |
63276 KiB |
| test_0056.txt |
AC |
535 ms |
64424 KiB |
| test_0057.txt |
AC |
546 ms |
64128 KiB |
| test_0058.txt |
AC |
631 ms |
63188 KiB |
| test_0059.txt |
AC |
608 ms |
65412 KiB |
| test_0060.txt |
AC |
567 ms |
63784 KiB |
| test_0061.txt |
AC |
544 ms |
64652 KiB |
| test_0062.txt |
AC |
537 ms |
64420 KiB |
| test_0063.txt |
AC |
633 ms |
61716 KiB |
| test_0064.txt |
AC |
557 ms |
64980 KiB |
| test_0065.txt |
AC |
558 ms |
64624 KiB |
| test_0066.txt |
AC |
553 ms |
62596 KiB |
| test_0067.txt |
AC |
556 ms |
63256 KiB |
| test_0068.txt |
AC |
616 ms |
64556 KiB |
| test_0069.txt |
AC |
623 ms |
62260 KiB |
| test_0070.txt |
AC |
563 ms |
62468 KiB |
| test_0071.txt |
AC |
612 ms |
63752 KiB |
| test_0072.txt |
AC |
551 ms |
64200 KiB |
| test_0073.txt |
AC |
577 ms |
64048 KiB |
| test_0074.txt |
AC |
556 ms |
64580 KiB |
| test_0075.txt |
AC |
582 ms |
64532 KiB |
| test_0076.txt |
AC |
683 ms |
64660 KiB |
| test_0077.txt |
AC |
556 ms |
62528 KiB |
| test_0078.txt |
AC |
611 ms |
65152 KiB |
| test_0079.txt |
AC |
566 ms |
63904 KiB |
| test_0080.txt |
AC |
560 ms |
63072 KiB |
| test_0081.txt |
AC |
531 ms |
64912 KiB |
| test_0082.txt |
AC |
542 ms |
63620 KiB |
| test_0083.txt |
AC |
584 ms |
65276 KiB |
| test_0084.txt |
AC |
561 ms |
63572 KiB |
| test_0085.txt |
AC |
643 ms |
65076 KiB |
| test_0086.txt |
AC |
549 ms |
64088 KiB |
| test_0087.txt |
AC |
584 ms |
63772 KiB |
| test_0088.txt |
AC |
614 ms |
65160 KiB |
| test_0089.txt |
AC |
542 ms |
65308 KiB |
| test_0090.txt |
AC |
605 ms |
63968 KiB |
| test_0091.txt |
AC |
554 ms |
64280 KiB |
| test_0092.txt |
AC |
570 ms |
64712 KiB |
| test_0093.txt |
AC |
606 ms |
63932 KiB |
| test_0094.txt |
AC |
584 ms |
64300 KiB |
| test_0095.txt |
AC |
618 ms |
62764 KiB |
| test_0096.txt |
AC |
549 ms |
64032 KiB |
| test_0097.txt |
AC |
594 ms |
64504 KiB |
| test_0098.txt |
AC |
567 ms |
65340 KiB |
| test_0099.txt |
AC |
563 ms |
64928 KiB |
| test_0100.txt |
AC |
580 ms |
64964 KiB |
| test_0101.txt |
AC |
562 ms |
64924 KiB |
| test_0102.txt |
AC |
573 ms |
64688 KiB |
| test_0103.txt |
AC |
541 ms |
66328 KiB |
| test_0104.txt |
AC |
534 ms |
64568 KiB |
| test_0105.txt |
AC |
567 ms |
63324 KiB |
| test_0106.txt |
AC |
565 ms |
63536 KiB |
| test_0107.txt |
AC |
561 ms |
64344 KiB |
| test_0108.txt |
AC |
549 ms |
63912 KiB |
| test_0109.txt |
AC |
579 ms |
64124 KiB |
| test_0110.txt |
AC |
596 ms |
65004 KiB |
| test_0111.txt |
AC |
562 ms |
64728 KiB |
| test_0112.txt |
AC |
541 ms |
64324 KiB |
| test_0113.txt |
AC |
538 ms |
64432 KiB |
| test_0114.txt |
AC |
627 ms |
64916 KiB |
| test_0115.txt |
AC |
619 ms |
65028 KiB |
| test_0116.txt |
AC |
550 ms |
63888 KiB |
| test_0117.txt |
AC |
591 ms |
63920 KiB |
| test_0118.txt |
AC |
665 ms |
62268 KiB |
| test_0119.txt |
AC |
550 ms |
64460 KiB |
| test_0120.txt |
AC |
611 ms |
63928 KiB |
| test_0121.txt |
AC |
618 ms |
64508 KiB |
| test_0122.txt |
AC |
630 ms |
63200 KiB |
| test_0123.txt |
AC |
556 ms |
63180 KiB |
| test_0124.txt |
AC |
554 ms |
63584 KiB |
| test_0125.txt |
AC |
555 ms |
64752 KiB |
| test_0126.txt |
AC |
558 ms |
64372 KiB |
| test_0127.txt |
AC |
545 ms |
65040 KiB |
| test_0128.txt |
AC |
583 ms |
63320 KiB |
| test_0129.txt |
AC |
551 ms |
64308 KiB |
| test_0130.txt |
AC |
566 ms |
64356 KiB |
| test_0131.txt |
AC |
533 ms |
65756 KiB |
| test_0132.txt |
AC |
551 ms |
65404 KiB |
| test_0133.txt |
AC |
553 ms |
62112 KiB |
| test_0134.txt |
AC |
579 ms |
65996 KiB |
| test_0135.txt |
AC |
601 ms |
62792 KiB |
| test_0136.txt |
AC |
546 ms |
65148 KiB |
| test_0137.txt |
AC |
583 ms |
64932 KiB |
| test_0138.txt |
AC |
548 ms |
64104 KiB |
| test_0139.txt |
AC |
587 ms |
65192 KiB |
| test_0140.txt |
AC |
565 ms |
65356 KiB |
| test_0141.txt |
AC |
552 ms |
63688 KiB |
| test_0142.txt |
AC |
546 ms |
65504 KiB |
| test_0143.txt |
AC |
561 ms |
63440 KiB |
| test_0144.txt |
AC |
560 ms |
64908 KiB |
| test_0145.txt |
AC |
546 ms |
64344 KiB |
| test_0146.txt |
AC |
547 ms |
65332 KiB |
| test_0147.txt |
AC |
605 ms |
63032 KiB |
| test_0148.txt |
AC |
554 ms |
64312 KiB |
| test_0149.txt |
AC |
559 ms |
63728 KiB |