use proconio::input; const N: usize = 2048; //const N: usize = 24; // https://zenn.dev/tipstar0125/articles/245bceec86e40a struct TimeKeeper { t_start: std::time::Instant, t_threshold: f64, } impl TimeKeeper { fn new(t_threshold: f64) -> Self { TimeKeeper { t_start: std::time::Instant::now(), t_threshold, } } #[inline] fn isTimeOver(&self) -> bool { let elapsed_time = self.t_start.elapsed().as_nanos() as f64 * 1e-9; #[cfg(feature = "local")] { elapsed_time * 0.85 >= self.t_threshold } #[cfg(not(feature = "local"))] { elapsed_time >= self.t_threshold } } } // XorShift // https://gemini.google.com/app/3ddaf2f301e50794?utm_source=app_launcher&utm_medium=owned&utm_campaign=base_all struct XorShift32 { state: u32, } impl XorShift32 { // 初期シード fn new(seed: u32) -> Self { XorShift32 { state: seed } } // 次の乱数を生成 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_bool_u8(&mut self) -> u8 { (self.next_u32() & 1) as u8 } } // ランダムに0,1 を256個出力する fn generate_arr(rng: &mut XorShift32) -> [u8; 256] { let mut res = [0_u8; 256]; for i in 0..256 { res[i] = rng.next_bool_u8(); } res } // 後ろの制約から決めていく fn generate_arr2( rng: &mut XorShift32, constraint: &Vec<(usize, usize, usize, u8, u8, u8)>, ) -> [u8; 256] { let mut res = [0_u8; 256]; for i in (0..N).rev() { let &(a, b, c, p, q, r) = &constraint[i]; let random = rng.next_u32(); match random % 3 { 0 => res[a] = p, 1 => res[b] = q, 2 => res[c] = r, _ => unreachable!(), } } res } // スコア計算 fn calc_score(arr: &[u8; 256], constraint: &Vec<(usize, usize, usize, u8, u8, u8)>) -> u32 { for i in 0..N { let &(a, b, c, p, q, r) = &constraint[i]; if (arr[a] != p) & (arr[b] != q) & (arr[c] != r) { return i as u32; } } N as u32 } // solver_dfc // 普通に深さ優先探索するとどうなる? fn dfs( arr: &mut [u8; 256], constraint: &Vec<(usize, usize, usize, u8, u8, u8)>, i: usize, rng: &mut XorShift32, timer: &TimeKeeper, ) -> (u32, [u8; 256]) { let mut best_score: u32 = i as u32; let mut best_arr: [u8; 256] = *arr; if timer.isTimeOver() | (i >= N){ return (best_score, best_arr); } let &(a, b, c, p, q, r) = &constraint[i]; // すでに条件達成済み if (arr[a] == p) | (arr[b] == q) | (arr[c] == r) { return dfs(arr, &constraint, i + 1, rng, &timer); } else { // ここから条件を動かす if arr[a] == 2 { arr[a] = p; let (score_tmp, arr_tmp) = dfs(arr, constraint, i + 1, rng, timer); if score_tmp > best_score { best_score = score_tmp; best_arr = arr_tmp; } arr[a] = 2; } if arr[b] == 2 { if timer.isTimeOver() { return (best_score, best_arr); } arr[b] = q; let (score_tmp, arr_tmp) = dfs(arr, constraint, i + 1, rng, timer); if score_tmp > best_score { best_score = score_tmp; best_arr = arr_tmp; } arr[b] = 2; } if arr[c] == 2 { if timer.isTimeOver() { return (best_score, best_arr); } arr[c] = r; let (score_tmp, arr_tmp) = dfs(arr, constraint, i + 1, rng, timer); if score_tmp > best_score { best_score = score_tmp; best_arr = arr_tmp; } arr[c] = 2; } return (best_score, best_arr); } } fn main() { // タイマー let timer = TimeKeeper::new(1.9); // 入力 input! { constraint:[(usize, usize, usize, u8,u8,u8);N] } // 乱数初期化 let mut rng = XorShift32::new(4869); let mut arr = [2_u8; 256]; let (_, best_arr) = dfs(&mut arr, &constraint, 0, &mut rng, &timer); // 出力 for &a in best_arr.iter().rev() { if a == 2 { print!("0") } else { print!("{a}") } } }