結果

問題 No.5020 Averaging
ユーザー rhoorhoo
提出日時 2024-02-27 21:03:41
言語 Rust
(1.77.0)
結果
AC  
実行時間 952 ms / 1,000 ms
コード長 7,500 bytes
コンパイル時間 3,247 ms
コンパイル使用メモリ 196,396 KB
実行使用メモリ 6,676 KB
スコア 86,822,180
最終ジャッジ日時 2024-02-27 21:04:35
合計ジャッジ時間 54,147 ms
ジャッジサーバーID
(参考情報)
judge15 / judge11
純コード判定しない問題か言語
このコードへのチャレンジ
(要ログイン)

テストケース

テストケース表示
入力 結果 実行時間
実行使用メモリ
testcase_00 AC 952 ms
6,676 KB
testcase_01 AC 952 ms
6,676 KB
testcase_02 AC 952 ms
6,676 KB
testcase_03 AC 952 ms
6,676 KB
testcase_04 AC 952 ms
6,676 KB
testcase_05 AC 951 ms
6,676 KB
testcase_06 AC 951 ms
6,676 KB
testcase_07 AC 952 ms
6,676 KB
testcase_08 AC 951 ms
6,676 KB
testcase_09 AC 952 ms
6,676 KB
testcase_10 AC 952 ms
6,676 KB
testcase_11 AC 952 ms
6,676 KB
testcase_12 AC 952 ms
6,676 KB
testcase_13 AC 951 ms
6,676 KB
testcase_14 AC 952 ms
6,676 KB
testcase_15 AC 951 ms
6,676 KB
testcase_16 AC 951 ms
6,676 KB
testcase_17 AC 952 ms
6,676 KB
testcase_18 AC 952 ms
6,676 KB
testcase_19 AC 952 ms
6,676 KB
testcase_20 AC 952 ms
6,676 KB
testcase_21 AC 952 ms
6,676 KB
testcase_22 AC 952 ms
6,676 KB
testcase_23 AC 952 ms
6,676 KB
testcase_24 AC 951 ms
6,676 KB
testcase_25 AC 951 ms
6,676 KB
testcase_26 AC 951 ms
6,676 KB
testcase_27 AC 952 ms
6,676 KB
testcase_28 AC 952 ms
6,676 KB
testcase_29 AC 952 ms
6,676 KB
testcase_30 AC 952 ms
6,676 KB
testcase_31 AC 951 ms
6,676 KB
testcase_32 AC 951 ms
6,676 KB
testcase_33 AC 952 ms
6,676 KB
testcase_34 AC 951 ms
6,676 KB
testcase_35 AC 952 ms
6,676 KB
testcase_36 AC 951 ms
6,676 KB
testcase_37 AC 952 ms
6,676 KB
testcase_38 AC 952 ms
6,676 KB
testcase_39 AC 952 ms
6,676 KB
testcase_40 AC 951 ms
6,676 KB
testcase_41 AC 952 ms
6,676 KB
testcase_42 AC 951 ms
6,676 KB
testcase_43 AC 952 ms
6,676 KB
testcase_44 AC 952 ms
6,676 KB
testcase_45 AC 951 ms
6,676 KB
testcase_46 AC 951 ms
6,676 KB
testcase_47 AC 952 ms
6,676 KB
testcase_48 AC 952 ms
6,676 KB
testcase_49 AC 952 ms
6,676 KB
権限があれば一括ダウンロードができます

ソースコード

diff #

#![allow(non_snake_case)]



// todo: 近傍の種類を増やす


fn main(){
    get_time();
    let mut scan=Scanner::new();
    input!{
        scan,
        n:usize,
        ab:[(i64,i64);n],
    }
    let pos=ab.into_iter().map(|t|P(t.0-MED,t.1-MED)).collect::<Vec<_>>();

    let mut log=[0.;65536];
    for i in 0..65536{
        log[i]=((i as f64+0.5)/65536.).ln();
    }
    rnd::shuffle(&mut log);

    let mut state=State::new(&pos);
    anneal(&mut state,0.2,0.7,&log); // todo
    eprintln!("first_score = {:.2}",state.calc_score());

    let mut tree=Tree::new(&pos,&state.ord);
    anneal(&mut tree,0.95,0.7,&log); // todo
    eprintln!("score = {:.2}",tree.calc_score());

    let ans=tree.restore();
    assert!(ans.len()==M);
    println!("\n{}",ans.len());
    for &(u,v) in &ans{
        println!("{} {}",u+1,v+1);
    }
}



#[derive(Clone)]
struct State<'a>{
    pos:&'a [P],
    ord:Vec<usize>,
    score:f64,
}
impl<'a> State<'a>{
    fn new(pos:&'a [P])->Self{
        let mut ret=Self{
            pos,
            ord:(1..N).collect::<Vec<_>>(),
            score:f64::INFINITY,
        };
        ret.score=ret.calc_score();
        ret
    }

    fn calc_score(&self)->f64{
        let mut p=self.pos[0];
        for &n in &self.ord{
            p=p.merge(self.pos[n]);
        }
        (p.0.abs().max(p.1.abs()) as f64).ln()
    }
}
impl<'a> AnnealState for State<'a>{
    fn score(&self)->f64{
        self.score
    }

    fn trans(&mut self,add:f64)->bool{
        // todo
        let i0=(0..3).map(|_|rnd::get(self.ord.len())).min().unwrap();
        let i1=(0..3).map(|_|rnd::range_skip(0,self.ord.len(),i0)).min().unwrap();
    
        self.ord.swap(i0,i1);
        let new=self.calc_score();
    
        if add>=(new-self.score) as f64{
            self.score=new;
            true
        } else{
            self.ord.swap(i0,i1);
            false
        }
    }
}


const FIX:usize=25; // todo


#[derive(Clone)]
struct Tree{
    fix:P,
    fix_ord:&'static [(usize,usize)],
    is:&'static [usize],
    pos:&'static [P],
    ord:Vec<(usize,usize)>,
    score:f64,
}
impl Tree{
    fn new(pos:&[P],ans:&[usize])->Self{
        let mut fix=P(0,0);
        let mut ord=vec![];
        let mut is=vec![!0;N];
        is[0]=0;
        let mut ps=vec![pos[0]];
        let mut fix_ord=vec![];
        
        for i in 0..ans.len(){
            if ans.len()-i<=FIX{
                fix=fix.merge(pos[ans[i]]);
                fix_ord.push((0,ans[i]));
            } else{
                is[i+1]=ans[i];
                ps.push(pos[ans[i]]);
                ord.push((0,i+1));
            }
        }
        assert!(ps.len()==N-FIX);

        ord.splice(0..0,std::iter::repeat(ord[0]).take(M-FIX-ord.len()));
        assert!(ord.len()+FIX==M);
        
        let mut ret=Tree{
            fix,ord,
            fix_ord:Box::leak(fix_ord.into_boxed_slice()),
            is:Box::leak(is.into_boxed_slice()),
            pos:Box::leak(ps.into_boxed_slice()),
            score:f64::INFINITY,
        };
        ret.score=ret.calc_score();
        ret
    }
    
    fn calc_score(&self)->f64{
        let mut pos:[P;N-FIX]=self.pos.try_into().unwrap();
        for &(u,v) in &self.ord{
            pos[u]=pos[u].merge(pos[v]);
            pos[v]=pos[u];
        }

        let i=(pos[0].0>>FIX)+self.fix.0;
        let j=(pos[0].1>>FIX)+self.fix.1;

        (i.abs().max(j.abs()) as f64).ln()
    }

    fn restore(&self)->Vec<(usize,usize)>{
        self.ord.iter().map(|&t|(self.is[t.0],self.is[t.1]))
            .chain(self.fix_ord.iter().copied())
            .collect()
    }
}
impl AnnealState for Tree{
    fn score(&self)->f64{
        self.score
    }

    fn trans(&mut self,add:f64)->bool{
        let i=(0..3).map(|_|rnd::get(self.ord.len())).min().unwrap();
        let u=if rnd::next()&1==0{ // todo
            0
        } else{
            rnd::get(self.pos.len())
        };
        let v=rnd::range_skip(0,self.pos.len(),u);

        let old=self.ord[i];
        if (u,v)==old || (v,u)==old{
            return false;
        }

        self.ord[i]=(u,v);
        let new=self.calc_score();
        if add>=(new-self.score) as f64{
            self.score=new;
            true
        } else{
            self.ord[i]=old;
            false
        }
    }
}



const N:usize=45;
const M:usize=50;
const MED:i64=5*1e17 as i64;


#[derive(Clone,Copy)]
struct P(i64,i64);
impl P{
    fn merge(self,a:Self)->Self{
        P((self.0+a.0)/2,(self.1+a.1)/2)
    }
}


fn get_time()->f64{
    static mut START:f64=0.;
    let time=std::time::SystemTime::now().duration_since(std::time::UNIX_EPOCH).unwrap().as_secs_f64();
    unsafe{
        if START==0.{
            START=time;
        }

        #[cfg(local)]{
            return (time-START)*1.;
        }
        time-START
    }
}



fn anneal<S:AnnealState>(state:&mut S,tl:f64,init_heat:f64,log:&[f64]){
    let start=get_time();
    let tl=tl-start;
    assert!(0.<tl);

    let mut iter=0;
    let mut heat=0.;

    let mut stay=0;
    let mut best=state.clone();

    while iter&255!=0 || {
        let time=(get_time()-start)/tl;
        heat=init_heat*(1.-time);
        time<=1.
    }{
        iter+=1;
        let add=-heat*log[iter&65535]; // 最小化
        // let add=0.;
        state.trans(add);

        stay+=1;
        if best.score()>state.score(){
            stay=0;
            best=state.clone();
        } else if stay>=1e5 as u64{ // todo
            stay=0;
            *state=best.clone();
        }
    }

    *state=best;
}


trait AnnealState:Clone{
    fn score(&self)->f64;
    fn trans(&mut self,add:f64)->bool;
}




#[allow(unused)]
mod rnd {
    static mut A:u64=1;

    pub fn next()->u32{
        unsafe{
            let mut x=A;
            A*=0xcafef00dd15ea5e5;
            x^=x>>22;
            (x>>22+(x>>61)) as u32
        }
    }

    pub fn nextf()->f64{
        unsafe{
            std::mem::transmute::<u64,f64>(0x3ff0000000000000|(next() as u64)<<20)-1.
        }
    }

    pub fn get(n:usize)->usize{
        assert!(n<=u32::MAX as usize);
        next() as usize*n>>32
    }

    pub fn range(a:usize,b:usize)->usize{
        assert!(a<b);
        get(b-a)+a
    }

    pub fn range_skip(a:usize,b:usize,skip:usize)->usize{
        assert!(a<=skip && skip<b);
        let n=range(a,b-1);
        n+(skip<=n) as usize
    }

    pub fn shuffle<T>(list:&mut [T]){
        for i in (0..list.len()).rev(){
            list.swap(i,get(i+1));
        }
    }
}



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<T:std::str::FromStr>(&mut self)->T{
        self.stack.next().unwrap().parse::<T>().unwrap_or_else(|_|panic!("parse error {}",std::any::type_name::<T>()))
    }
}


#[macro_export]
macro_rules! input{
    ($scan:expr $(,)?)=>{};
    ($scan:expr, $name:ident:$t:tt $($rest:tt)*)=>{
        let $name=read_value!($scan,$t);
        input!{$scan $($rest)*}
    };
}

#[macro_export]
macro_rules! read_value{
    ($scan:expr, ($($t:tt),*))=>{
        ($(read_value!($scan, $t)),*)
    };
    ($scan:expr, [$t:tt;$len:expr])=>{
        (0..$len).map(|_|read_value!($scan,$t)).collect::<Vec<_>>()
    };
    ($scan:expr, $t:ty)=>{
        $scan.read::<$t>()
    };
}
0