#![allow(non_snake_case)] fn main(){ let state=State::new(); let initial=Cand{ act:NULL, hash:0, score:0, rem:0, leaf:0, active:true, }; let ans=beam_search(state,initial); let input=get_input(); assert!(ans.len()<=input.t); println!("{}",ans.len()); for node in &ans{ let i=node.act.i; let j=node.act.j; println!("{} {}",i,j); } } fn beam_search(state:State,initial:Cand)->Vec{ let input=get_input(); let WIDTH=30; let mut beam=BeamSearch::new(state,initial); let mut is=vec![vec![vec![];N];N]; let mut set=std::collections::HashSet::new(); let mut best_score=0; let mut best=vec![]; for turn in 0..input.t{ if turn!=0{ let arg=(0..beam.cand.len()).max_by_key(|&i|beam.cand[i].score).unwrap(); if best_scorei64{ cand.score+(cand.rem.min(input.t-turn)) as i64*200 // todo }; for p in iterp(N,N){ is[p].sort_unstable_by_key(|&i|-eval(&beam.cand[i])); set.clear(); let mut cnt=0; for &i in &is[p]{ if set.insert(beam.cand[i].hash){ beam.select(i); cnt+=1; if cnt>=WIDTH{ break; } } } } } beam.run(); if beam.cand.is_empty(){ eprintln!("end = {}",turn); break; } } if !beam.cand.is_empty(){ let arg=(0..beam.cand.len()).max_by_key(|&i|beam.cand[i].score).unwrap(); if best_score){ let mut add_cand=|new:Cand|{ assert!(new.leaf==leaf); assert!(!new.active); next_cand.push(new); }; let a=&get_input().a; let zob=get_zob(); if cand.act==NULL{ let mut hash=0; for p in iterp(N,N){ hash^=zob[p]; } // 最初のマスは自由 for p in iterp(N,N){ let new=Cand{ act:p, hash:hash^zob[p], score:a[p], rem:N*N-1, leaf,active:false, }; add_cand(new); } return; } for dd in DD{ let np=cand.act+dd; if !np.in_range(N,N) || state.vis[np]{ continue; } // rem,hashの計算 // bfs state.vis[np]=true; state.at+=1; let mut hash=cand.hash^zob[np]; let mut rem=cand.rem-1; let mut skip=0; let mut max=0; let mut max_hash=0; 'a: for ddn in DD{ let nnp=np+ddn; if !nnp.in_range(N,N) || state.vis[nnp] || state.seen[nnp]==state.at{ continue; } state.que.clear(); state.que.push_back(nnp); state.seen[nnp]=state.at; let mut cnt=0; let mut new=0; while let Some(v)=state.que.pop_front(){ if cnt>=10{ for ddm in DD{ let nnp=np+ddm; if nnp.in_range(N,N) && state.vis[nnp] && state.seen[nnp]!=state.at{ skip+=1; continue 'a; } } } cnt+=1; new^=zob[v]; for ddx in DD{ let nv=v+ddx; if nv.in_range(N,N) && !state.vis[nv] && state.seen[nv]!=state.at{ state.seen[nv]=state.at; state.que.push_back(nv); } } } rem-=cnt; hash^=new; if max, at:usize, seen:[[usize;N];N], } impl State{ fn new()->State{ State{ vis:[[false;N];N], que:VecDeque::new(), at:0, seen:[[0;N];N], } } fn apply(&mut self,node:&Node){ self.vis[node.act]=true; } fn revert(&mut self,node:&Node){ self.vis[node.act]=false; } } #[derive(Clone)] struct Cand{ act:P, hash:u64, // 訪れることができるマスのハッシュ score:i64, rem:usize, leaf:usize, active:bool, } impl Cand{ fn to_node(&self)->Node{ Node{ act:self.act, } } } #[derive(Clone,Copy)] struct Node{ act:P, } struct BeamSearch{ state:State, trace:Vec, tour:Vec, leaf:Vec, cand:Vec, next_tour:Vec, next_leaf:Vec, next_cand:Vec, } impl BeamSearch{ fn new(state:State,initial:Cand)->Self{ Self{ state, trace:vec![], tour:vec![], leaf:vec![0], cand:vec![initial], next_tour:vec![], next_leaf:vec![], next_cand:vec![], } } fn run(&mut self){ let turn=self.trace.len(); self.trace.push(self.cand.last().unwrap().to_node()); if turn==0{ expand(&mut self.state,&self.cand[0],0,&mut self.next_cand); std::mem::swap(&mut self.cand,&mut self.next_cand); return; } self.next_tour.clear(); self.next_leaf.clear(); self.next_cand.clear(); let mut f=0; let mut li=self.leaf.len()-1; for cand in self.cand.iter().rev().filter(|cand|cand.active){ let lca=self.leaf[cand.leaf..li].iter().rev() .fold((0,self.leaf[li]),|(a,b),&x|(a.max(b-x),x)).0; self.trace[turn-lca..turn+f].iter().rev().for_each(|node|self.state.revert(node)); f=1; self.next_tour.extend_from_slice(&self.trace[turn-lca..]); self.trace[turn]=cand.to_node(); let mut prog=0; for w in self.leaf[cand.leaf..=li].windows(2){ let rank=w[1]-w[0]; if progVec{ let mut ret=self.trace[1..].to_vec(); let len=ret.len(); let mut prog=0; for w in self.leaf[self.cand[idx].leaf..].windows(2){ let rank=w[1]-w[0]; if prog{ fn $a()->&'static $t{ use std::sync::OnceLock; static D:OnceLock<$t>=OnceLock::new(); D.get_or_init(||$e) } } } // LURD const DD:[P;4]=[P{i:0,j:!0},P{i:!0,j:0},P{i:0,j:1},P{i:1,j:0}]; const DX:[P;8]=[P{i:0,j:!0},P{i:!0,j:!0},P{i:!0,j:0},P{i:!0,j:1},P{i:0,j:1},P{i:1,j:1},P{i:1,j:0},P{i:1,j:!0}]; #[derive(Clone,Copy,PartialEq,Eq,PartialOrd,Ord,Hash,Default)] struct P{ i:usize, j:usize, } impl P{ fn new(i:usize,j:usize)->P{ P{i,j} } fn in_range(self,h:usize,w:usize)->bool{ self.iusize{ self.i*w+self.j } fn from(id:usize,w:usize)->P{ P::new(id/w,id%w) } fn manh(self,p:P)->usize{ let abs_diff=|a,b|(a as i64-b as i64).abs() as usize; abs_diff(self.i,p.i)+abs_diff(self.j,p.j) } fn dir(self,p:P)->usize{ if self.i==p.i{ if self.j-1==p.j{ 0 } else{ assert!(self.j+1==p.j); 2 } } else{ if self.i-1==p.i{ 1 } else{ assert!(self.i+1==p.i); 3 } } } } impl std::fmt::Debug for P{ fn fmt(&self,f:&mut std::fmt::Formatter)->std::fmt::Result{ write!(f,"({}, {})",self.i,self.j) } } impl std::ops::Add for P{ type Output=P; fn add(self,a:P)->P{ P{ i:self.i+a.i, j:self.j+a.j, } } } impl std::ops::Sub for P{ type Output=P; fn sub(self,a:P)->P{ P{ i:self.i-a.i, j:self.j-a.j, } } } impl std::ops::Mul for P{ type Output=P; fn mul(self,a:usize)->P{ P{ i:self.i*a, j:self.j*a, } } } impl std::ops::Div for P{ type Output=P; fn div(self,a:usize)->P{ P{ i:self.i/a, j:self.j/a, } } } impl std::ops::Neg for P{ type Output=P; fn neg(self)->P{ P{ i:self.i.wrapping_neg(), j:self.j.wrapping_neg(), } } } macro_rules! impl_p_ops{ ($t:ty,$assign_trait:ident,$assign_func:ident,$op:tt)=>{ impl std::ops::$assign_trait<$t> for P{ fn $assign_func(&mut self,a:$t){ *self=*self $ op a; } } } } impl_p_ops!(P,AddAssign,add_assign,+); impl_p_ops!(P,SubAssign,sub_assign,-); impl_p_ops!(usize,MulAssign,mul_assign,*); impl_p_ops!(usize,DivAssign,div_assign,/); macro_rules! impl_p_index{ ($t:ty)=>{ impl> std::ops::Index

for $t{ type Output=T::Output; fn index(&self,idx:P)->&T::Output{ &self[idx.i][idx.j] } } impl> std::ops::IndexMut

for $t{ fn index_mut(&mut self,idx:P)->&mut T::Output{ &mut self[idx.i][idx.j] } } } } impl_p_index!([T]); impl_p_index!(Vec); fn iterp(h:usize,w:usize)->impl Iterator{ (0..h).map(move|i|(0..w).map(move|j|P::new(i,j))).flatten() } #[allow(unused)] mod rnd{ static mut X2:u32=12345; static mut X3:u32=0xcafef00d; static mut C_X1:u64=0xd15ea5e5<<32|23456; pub fn set_seed(seed:u64){ unsafe{ C_X1^=seed as u64; } } pub fn next()->u32{ unsafe{ let x=X3 as u64*3487286589; let ret=(X3^X2)+(C_X1 as u32^(x>>32) as u32); X3=X2; X2=C_X1 as u32; C_X1=x+(C_X1>>32); ret } } pub fn next64()->u64{ (next() as u64)<<32|next() as u64 } pub fn nextf()->f64{ f64::from_bits(0x3ff0000000000000|(next() as u64)<<20)-1. } pub fn get(n:usize)->usize{ assert!(0>32 } pub fn range(a:usize,b:usize)->usize{ assert!(ausize{ assert!(a<=skip && skipi64{ assert!(a(a:&mut [T]){ for i in (1..a.len()).rev(){ a.swap(i,get(i+1)); } } pub fn shuffle_iter(a:&mut [T])->impl Iterator{ (0..a.len()).rev().map(|i|{ a.swap(i,get(i+1)); a[i] }) } } #[allow(unused)] trait RandomChoice{ type Output; fn choice(&self)->&Self::Output; } impl RandomChoice for [T]{ type Output=T; fn choice(&self)->&T{ &self[rnd::get(self.len())] } }