#![allow(non_snake_case)] fn optimize(input:&In,pos:&[P],id:usize,route:&[usize],target:&[usize])->(P,i64){ let mut coeff=[(0,0,0);2]; let mut update=|n:usize|{ // k(a-x)^2=kx^2-2kax+ka^2 let (pos,k)=if n, } impl State{ fn new()->State{ let mut route:Vec<_>=(0..N).chain(once(0)).collect(); rnd::shuffle(&mut route[1..N]); let mut cnt=[1;N]; cnt[0]=2; let pos=[();M].map(|_|P::rand(0,L)); State{pos,cnt,route} } fn score(&self,input:&In)->i64{ self.route.windows(2).map(|w|self.dist(input,w[0],w[1])).sum() } fn dist(&self,input:&In,a:usize,b:usize)->i64{ if a=N && b>=N{ (self.pos[a-N]-self.pos[b-N]).abs2() } else if a>=N{ ALPHA*(self.pos[a-N]-input.pos[b]).abs2() } else{ ALPHA*(self.pos[b-N]-input.pos[a]).abs2() } } // idxは+Nされたあと fn change(&mut self,input:&In,id:usize,new:P,add:i64,score:&mut i64,BF:&mut BUF)->bool{ BF.V.clear(); BF.target.clear(); let mut prev=self.route[0]; BF.V.push(prev); let mut new_score=0; let backup=self.pos[id-N]; self.pos[id-N]=new; let mut f=false; for &n in &self.route[1..]{ if n!=id{ let diff0=self.dist(input,prev,n); let diff1=self.dist(input,prev,id)+self.dist(input,id,n); if diff1i64{ assert!(a+2<=b); let (a0,a1)=(self.route[a-1],self.route[a]); let (b0,b1)=(self.route[b-1],self.route[b]); self.dist(input,a0,b0)+self.dist(input,a1,b1)-self.dist(input,a0,a1)-self.dist(input,b0,b1) } fn two_opt(&mut self,a:usize,b:usize){ self.route[a..b].reverse(); } fn try_insert(&self,input:&In,a:usize,b:usize)->i64{ let (a0,a1)=(self.route[a-1],self.route[a]); self.dist(input,a0,b)+self.dist(input,b,a1)-self.dist(input,a0,a1) } fn insert(&mut self,a:usize,b:usize){ self.route.insert(a,b); if bi64{ let (a0,a1,a2)=(self.route[a-1],self.route[a],self.route[a+1]); assert!(a1>=N || self.cnt[a1]>1); self.dist(input,a0,a2)-self.dist(input,a0,a1)-self.dist(input,a1,a2) } fn remove(&mut self,idx:usize){ let n=self.route.remove(idx); if nbool{ if it%20==0{ let id=rnd::next()%M; let pos=state.pos[id]; let mut np; loop{ np=pos+P::rand(-D,D); if np.in_range(){ break; } } state.change(input,id+N,np,add,score,BF) } else{ let n=[0,0,0,0,0,0,1,1,2,2].choice(); match n{ 0=>{ let mut a=rnd::range(1,state.route.len()); let mut b; loop{ b=rnd::range(1,state.route.len()); if 2b{ std::mem::swap(&mut a,&mut b); } let diff=state.try_two_opt(input,a,b); if diff<=add{ *score+=diff; state.two_opt(a,b); true } else{ false } } 1=>{ let idx=rnd::range(1,state.route.len()); let mut n; let mut diff; loop{ n=rnd::next()%(N+M); diff=state.try_insert(input,idx,n); if diff!=0{ break; } } if diff<=add{ *score+=diff; state.insert(idx,n); true } else{ false } } 2=>{ let mut ty=0; let mut idx; loop{ idx=rnd::range(1,state.route.len()-1); if state.route[idx]>=N || state.cnt[state.route[idx]]>1{ break; } else{ ty+=1; if ty>=10{ return false; } } } let diff=state.try_remove(input,idx); if diff<=add{ *score+=diff; state.remove(idx); true } else{ false } } _=>panic!() } } } fn sa_tsp(input:&In,TL:f64)->([P;M],Vec){ let mut BF=BUF::default(); let mut ans_score=i64::MAX; let mut ans_state=([P(0,0);M],vec![]); let mut iter_sum=0; let mut valid=0; let mut th=[0;64]; let mut D=0; const I:usize=6; for i in 0..I{ let mut state=State::new(); let mut score=state.score(input); let start=get_time(); let TL=TL*(i+1) as f64/I as f64-start; let mut iter=0; let mut best=i64::MAX; let mut best_state=state.clone(); let mut ty=0; loop{ if iter&255==0{ let time=(get_time()-start)/TL; if time>=1.{ break; } const T:f64=35000.; let heat=T*(1.-time.powf(0.5)); th.fill_with(||(-heat*rnd::nextf().ln()) as i64); const D0:f64=300.; const D1:f64=10.; D=(D0+(D1-D0)*time.powf(1.5)).round() as i64; } iter+=1; valid+=trans(input,&mut state,iter,th[iter&63],D,&mut score,&mut BF) as usize; if best>score{ best=score; best_state=state.clone(); ty=0; } else{ ty+=1; if ty>=150000{ ty=0; state=best_state.clone(); score=best; } } } eprintln!("# try{}: {}",i,to(score)); assert_eq!(score,state.score(input)); iter_sum+=iter; if ans_score>best{ ans_score=best; ans_state=(best_state.pos,best_state.route); } } eprintln!("iter = {}",iter_sum); eprintln!("ratio = {:.4}",valid as f64/iter_sum as f64); eprintln!("best = {}",to(ans_score)); eprintln!("len = {}",ans_state.1.len()); ans_state } fn solve(input:&In)->([P;M],Vec){ let (mut pos,route)=sa_tsp(&input,0.9); let mut dists=[[-1;N+M];N+M]; let mut next=[[0;N+M];N+M]; for i in 0..N+M{ let (p0,k0)=if i=route.into_iter().filter(|&n|ni64{ (1e9/(1e3+(score as f64).sqrt())).round() as i64 } const N:usize=100; const M:usize=8; const L:i64=1001; const ALPHA:i64=5; struct In{ pos:[P;N], dist:[[i64;N];N] } impl In{ fn input()->In{ let mut scan=Scanner::new(); input!{ scan, n:usize, m:usize, tp:[(usize,usize);N] } assert_eq!((n,m),(N,M)); let pos:[P;N]=tp.iter().map(|&(a,b)|P(a as i64,b as i64)).collect::>().try_into().unwrap(); let mut dist=[[-1;N];N]; for i in 0..N{ for j in 0..N{ dist[i][j]=(pos[i]-pos[j]).abs2()*ALPHA*ALPHA; } } for k in 0..N{ for i in 0..N{ for j in 0..N{ dist[i][j]=dist[i][j].min(dist[i][k]+dist[k][j]); } } } In{pos,dist} } } #[derive(Default)] struct BUF{ V:Vec, target:Vec } #[macro_export]#[cfg(not(local))]macro_rules! eprint{($($_:tt)*)=>{}} #[macro_export]#[cfg(not(local))]macro_rules! eprintln{($($_:tt)*)=>{}} fn get_time()->f64{ static mut START:f64=-1.; let time=std::time::SystemTime::now().duration_since(std::time::UNIX_EPOCH).unwrap().as_secs_f64(); unsafe{ if START<0.{ START=time; } #[cfg(local)]{ (time-START)*2. } #[cfg(not(local))]{ time-START } } } struct Scanner{ stack:std::str::SplitAsciiWhitespace<'static> } impl Scanner{ fn new()->Self{ use std::io::Read; let mut tmp=String::new(); std::io::stdin().read_to_string(&mut tmp).unwrap(); Self{stack:Box::leak(tmp.into_boxed_str()).split_ascii_whitespace()} } fn read(&mut self)->T{ self.stack.next().unwrap().parse::().unwrap_or_else(|_|panic!("parse error {}",std::any::type_name::())) } } #[macro_export] macro_rules! input{ ($scan:ident, $($rest:tt)*)=>{ input_inner!{$scan,$($rest)*} }; } #[macro_export] macro_rules! input_inner{ ($scan:ident $(,)?)=>{}; ($scan:ident, $name:ident:$t:tt $($rest:tt)*)=>{ let $name=read_value!($scan,$t); input_inner!{$scan $($rest)*} }; } #[macro_export] macro_rules! read_value{ ($scan:ident, ($($t:tt),*))=>{ ($(read_value!($scan, $t)),*) }; ($scan:ident, [$t:tt;$len:expr])=>{ (0..$len).map(|_|read_value!($scan,$t)).collect::>() }; ($scan:ident, Chars)=>{ read_value!($scan,String).chars().collect::>() }; ($scan:ident, Usize1)=>{ read_value!($scan,usize)-1 }; ($scan:ident, $t:ty)=>{ $scan.read::<$t>() }; } mod rnd { static mut S:usize=88172645463325252; pub fn next()->usize{ unsafe{ S^=S<<7; S^=S>>9; S } } pub fn nextf()->f64{ f64::from_bits((0x3ff0000000000000|next()&0xfffffffffffff) as u64)-1. } pub fn range(a:usize,b:usize)->usize{ next()%(b-a)+a } pub fn rangei(a:i64,b:i64)->i64{ (next()%((b-a) as usize)) as i64+a } pub fn shuffle(list:&mut [T]){ for i in (0..list.len()).rev(){ list.swap(i,next()%(i+1)); } } } trait RandomChoice{ type Output; fn choice(&self)->&Self::Output; } impl RandomChoice for [T]{ type Output=T; fn choice(&self)->&T{ &self[rnd::next()%self.len()] } } #[derive(Clone,Copy,PartialEq,Default,Debug)] struct P(i64,i64); impl P{ fn rand(a:i64,b:i64)->P{ P(rnd::rangei(a,b),rnd::rangei(a,b)) } fn in_range(self)->bool{ (self.0 as usize)i64{ self.0*self.0+self.1*self.1 } } use std::ops::*; impl Add for P{ type Output=P; fn add(self,a:P)->P{ P(self.0+a.0,self.1+a.1) } } impl Sub for P{ type Output=P; fn sub(self,a:P)->P{ P(self.0-a.0,self.1-a.1) } } impl AddAssign for P{ fn add_assign(&mut self,a:P){ *self=*self+a; } } impl SubAssign for P{ fn sub_assign(&mut self,a:P){ *self=*self-a; } } // wataさんのTSPSolver fn compute_cost(dist:&Vec>,route:&[usize])->i64{ route.windows(2).map(|w|dist[w[0]][w[1]]).sum() } // mv: (i, dir) fn apply_move(tour:&mut [usize],idx:&mut [usize],mv:&[(usize,usize);K],BF:&mut Vec){ let mut ids=[!0;K]; let mut it=0..; ids.fill_with(||it.next().unwrap()); ids.sort_unstable_by_key(|&i|mv[i].0); let mut order=[0;K]; for i in 0..K{ order[ids[i]]=i; } let mut i=ids[0]; let mut dir=0; BF.clear(); loop{ let (j,rev)=if dir==mv[i].1{ ((i+1)%K,0) } else{ ((i+K-1)%K,1) }; if mv[j].1==rev{ if order[j]==K-1{ break; } i=ids[order[j]+1]; dir=0; BF.extend_from_slice(&tour[mv[j].0+1..mv[i].0+1]); } else{ i=ids[order[j]-1]; dir=1; BF.extend(tour[mv[i].0+1..mv[j].0+1].iter().rev().cloned()); } } assert_eq!(BF.len(),mv[ids[K-1]].0-mv[ids[0]].0); tour[mv[ids[0]].0+1..mv[ids[K-1]].0+1].copy_from_slice(&BF); for i in mv[ids[0]].0+1..mv[ids[K-1]].0+1{ idx[tour[i]]=i; } } const FEASIBLE3:[bool;64]=[false,false,false,true,false,true,true,true,true,true,true,false,true,false,false,false,false,false,false,false,false,false,false,false,false,false,false,true,false,true,true,true,true,true,true,false,true,false,false,false,false,false,false,false,false,false,false,false,false,false,false,true,false,true,true,true,true,true,true,false,true,false,false,false]; fn tsp(dist:&Vec>,mut route:Vec,TL:f64)->Vec{ let n=dist.len(); assert_eq!(n,route.len()-1); let mut f=vec![vec![];n]; for i in 0..n{ for j in 0..n{ if i!=j{ f[i].push((dist[i][j],j)); } } f[i].sort_unstable_by(|&(a,_),&(b,_)|a.partial_cmp(&b).unwrap()); } let mut idx=vec![!0;n]; let (mut min_score,mut best)=(compute_cost(&dist,&route),route.clone()); let mut BF=vec![]; while get_time()0{ cost-=diff; apply_move(&mut route,&mut idx,&[(i,di),(j,dj)],&mut BF); ok=true; break 'outer; } for &(jk,vk) in &f[route[j+dj]]{ if gain-jk<=0{ break; } for dk in 0..2{ let k=if idx[vk]==0 && dk==0{ n-1 } else { idx[vk]-1+dk }; if i==k || j==k{ continue; } let diff=gain-jk+dist[route[k]][route[k+1]]-dist[route[k+dk]][route[i+1-di]]; if diff>0{ let mask=((icost{ min_score=cost; best=route; } route=best.clone(); loop{ if rnd::next()&1==0{ // double bridge let mut is=[!0;4]; is.fill_with(||rnd::next()%n+1); is.sort_unstable(); if is[0]==is[1] || is[1]==is[2] || is[2]==is[3]{ continue; } BF.clear(); let it=route[is[2]..is[3]].iter().chain(&route[is[1]..is[2]]).chain(&route[is[0]..is[1]]); BF.extend(it.cloned()); route[is[0]..is[3]].copy_from_slice(&BF); } else{ for _ in 0..6{ loop{ let i=rnd::next()%(n-1); let j=rnd::next()%(n-1); if i