結果
問題 | No.5016 Worst Mayor |
ユーザー |
|
提出日時 | 2023-04-29 15:09:27 |
言語 | Rust (1.83.0 + proconio) |
結果 |
AC
|
実行時間 | 259 ms / 2,000 ms |
コード長 | 11,599 bytes |
コンパイル時間 | 1,985 ms |
コンパイル使用メモリ | 170,776 KB |
実行使用メモリ | 53,652 KB |
スコア | 7,817,232,180 |
平均クエリ数 | 400.00 |
最終ジャッジ日時 | 2023-04-29 15:09:50 |
合計ジャッジ時間 | 17,851 ms |
ジャッジサーバーID (参考情報) |
judge11 / judge15 |
純コード判定しない問題か言語 |
(要ログイン)
ファイルパターン | 結果 |
---|---|
other | AC * 50 |
コンパイルメッセージ
warning: variable `debug` is assigned to, but never used --> Main.rs:137:13 | 137 | let mut debug=(0,0); | ^^^^^ | = note: consider using `_debug` instead = note: `#[warn(unused_variables)]` on by default warning: value assigned to `debug` is never read --> Main.rs:143:17 | 143 | debug=(i,j); | ^^^^^ | = help: maybe it is overwritten before being read? = note: `#[warn(unused_assignments)]` on by default warning: unused variable: `input` --> Main.rs:155:12 | 155 | fn sa_path(input:&IO)->Vec<P>{ | ^^^^^ help: if this is intentional, prefix it with an underscore: `_input` warning: unnecessary `unsafe` block --> Main.rs:300:5 | 300 | unsafe{ | ^^^^^^ unnecessary `unsafe` block | = note: `#[warn(unused_unsafe)]` on by default warning: function `sa_path` is never used --> Main.rs:155:4 | 155 | fn sa_path(input:&IO)->Vec<P>{ | ^^^^^^^ | = note: `#[warn(dead_code)]` on by default warning: function `etime` is never used --> Main.rs:299:4 | 299 | fn etime(){ | ^^^^^ warning: constant `DX` is never used --> Main.rs:449:7 | 449 | const DX:[P;8]=[P(0,-1),P(-1,-1),P(-1,0),P(-1,1),P(0,1),P(1,1),P(1,0),P(1,-1)]; | ^^ warning: static `S` is never used --> Main.rs:271:16 | 271 | static mut S:usize=88172645463325252; | ^ warning: function `next` is never used --> Main.rs:273:12 | 273 | pub fn next()->usize{ | ^^^^ warning: function `nextf` is never used --> Main.rs:281:12 | 281 | pub fn nextf()->f64{ | ^^^^^ warning: function `range` is never used --> Main.rs:285:12 | 285 | pub fn range(a:usize,b:usize)->usize{ | ^^^^^ warning: 11 warnings emitted
ソースコード
#![allow(non_snake_case)]struct Dij{edge:Vec<Vec<Vec<(P,f64,bool)>>>}impl Dij{fn new()->Dij{let mut edge=vec![vec![vec![];L];L];for i in 0..L{for j in 0..L{let pos=P(i as i64,j as i64);for k in 0..4{let np=pos+DD[k];if np.in_range(){edge[pos].push((np,1.,false));}}}}Dij{edge}}// 一応2つのque使えばlogが消せるが、、fn solve(&self,start:P)->Vec<Vec<(f64,i64)>>{let mut que=BinaryHeap::new();let mut ret=vec![vec![(INFINITY,-1);L];L];ret[start]=(0.,0);que.push(S(0.,(start,0)));while let Some(S(dist,(pos,cnt)))=que.pop(){if ret[pos].0!=dist{continue;}for &(np,cost,f) in &self.edge[pos]{let nd=cost+dist;if nd<ret[np].0{ret[np].0=nd;ret[np].1=cnt+f as i64;que.push(S(nd,(np,cnt+f as i64)));}}}ret}}fn solve_dp(input:&IO,builds:&[(P,P)])->Vec<Action>{assert!(builds.len()<=T);// scoresをどうにかして計算するlet mut min_dist:Vec<_>=input.data.iter().map(|&(a,b)|((a-b).abs() as f64,0)).collect();let mut scores:Vec<i64>=vec![0];let mut grid=Dij::new();for &(a,b) in builds{let edge=&mut grid.edge[a];for i in 0..edge.len(){if edge[i].0==b{assert!(!edge[i].2);edge[i].1=C;edge[i].2=true;}}let edge=&mut grid.edge[b];for i in 0..edge.len(){if edge[i].0==a{assert!(!edge[i].2);edge[i].1=C;edge[i].2=true;}}let dists=grid.solve(a);for (i,&(a,b)) in input.data.iter().enumerate(){let dist=dists[a].0+dists[b].0;let cnt=dists[a].1+dists[b].1;if min_dist[i].0>dist{min_dist[i].0=dist;min_dist[i].1=cnt;}}let score:i64=min_dist.iter().map(|(_,a)|a).sum();scores.push(score*D);}assert_eq!(scores.len(),builds.len()+1);const INF:i64=std::i64::MAX/4;const MAX_PEOPLE:usize=101;// DP[t][i][j]:=tターンで人がi人いてjまで建設が終わっているときの最大の金let mut dp0=vec![vec![(-INF,Rc::new(Nil));builds.len()+1];MAX_PEOPLE];dp0[1][0].0=INIT_MONEY;for _ in 1..=T{let mut dp1=vec![vec![(-INF,Rc::new(Nil));builds.len()+1];MAX_PEOPLE];for j in 0..MAX_PEOPLE{for k in 0..=builds.len(){// 建設するif k!=builds.len() && j!=0{let new=dp0[j][k].0-(1e7/(j as f64).sqrt()) as i64;if new>=0{let new=new+scores[k+1];if dp1[j][k+1].0<new{dp1[j][k+1]=(new,Rc::new(Cons{v:Build(builds[k]),prev:dp0[j][k].1.clone()}));}}}// 協力者を集めるif j!=MAX_PEOPLE-1{let new=dp0[j][k].0+scores[k];if dp1[j+1][k].0<new{dp1[j+1][k]=(dp0[j][k].0,Rc::new(Cons{v:People,prev:dp0[j][k].1.clone()}));}}// 資金集めをするlet new=dp0[j][k].0+MONEY+scores[k];if dp1[j][k].0<new{dp1[j][k]=(new,Rc::new(Cons{v:Money,prev:dp0[j][k].1.clone()}));}}}std::mem::swap(&mut dp0,&mut dp1);}let mut best=0;let mut arg=Rc::new(Nil);let mut debug=(0,0);for i in 0..MAX_PEOPLE{for j in 0..=builds.len(){if dp0[i][j].0>best{best=dp0[i][j].0;arg=dp0[i][j].1.clone();debug=(i,j);}}}eprintln!("best = {}",best);eprintln!("debug = {:?}",debug);arg.restore()}fn sa_path(input:&IO)->Vec<P>{todo!();}fn solve(input:&IO)->Vec<Action>{let mut builds=vec![];builds.push((P(7,7),P(7,8)));builds.push((P(7,7),P(7,6)));builds.push((P(7,8),P(7,9)));builds.push((P(7,6),P(7,5)));builds.push((P(7,9),P(7,10)));builds.push((P(7,5),P(7,4)));builds.push((P(7,10),P(7,11)));builds.push((P(7,4),P(7,3)));builds.push((P(7,11),P(7,12)));builds.push((P(7,2),P(7,1)));builds.push((P(7,12),P(7,13)));solve_dp(input,&builds)}fn main(){let IO=IO::input();let ans=solve(&IO);IO.output(&ans);}use std::f64::INFINITY;use std::collections::BinaryHeap;#[derive(Clone,Copy,PartialEq,Eq,Debug)]enum Action{Build((P,P)),People,Money}use Action::*;const N:usize=3000;const T:usize=400;const C:f64=0.223;const INIT_MONEY:i64=1e6 as i64;const MONEY:i64=0;const L:usize=14;const D:i64=60;struct IO{scan:Scanner,data:[(P,P);N]}impl IO{fn input()->IO{let mut scan=Scanner::new();input!{scan,n:usize,t:usize,d:[((Usize1,Usize1),(Usize1,Usize1));N]}assert_eq!((n,t),(N,T));let data=d.into_iter().map(|((a,b),(c,d))|(P(a as i64,b as i64),P(c as i64,d as i64))).collect::<Vec<_>>();IO{scan,data:data.try_into().unwrap()}}fn output(self,ans:&[Action]){assert_eq!(ans.len(),T);let mut scan=self.scan;for &act in ans{#[cfg(not(local))]{input!{scan,_u:usize,_v:usize,}}match act{Build((P(a,b),P(c,d)))=>println!("1 {} {} {} {}",a+1,b+1,c+1,d+1),People=>println!("2"),Money=>println!("3")}}}}#[macro_export] macro_rules! eprint{($($_:tt)*)=>{}}#[macro_export] 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)*1.6}#[cfg(not(local))]{time-START}}}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}}#[macro_export]macro_rules! timer{()=>{let _timer=Timer(get_time());}}static mut TIME:f64=0.;fn etime(){unsafe{eprintln!("{:.3}",TIME);}}struct Timer(f64);impl Drop for Timer{fn drop(&mut self){unsafe{TIME+=get_time()-self.0}}}struct Scanner{stack:std::str::SplitAsciiWhitespace<'static>}impl Scanner{fn new()->Self{Self{stack:"".split_ascii_whitespace()}}fn read<T:std::str::FromStr>(&mut self)->T{loop{if let Some(v)=self.stack.next(){return v.parse::<T>().unwrap_or_else(|_|panic!("{}: parse error",std::any::type_name::<T>()));}let mut tmp=String::new();std::io::stdin().read_line(&mut tmp).unwrap();assert!(!tmp.is_empty());self.stack=Box::leak(tmp.into_boxed_str()).split_ascii_whitespace();}}}#[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::<Vec<_>>()};($scan:ident, Chars)=>{read_value!($scan,String).chars().collect::<Vec<char>>()};($scan:ident, Usize1)=>{read_value!($scan,usize)-1};($scan:ident, $t:ty)=>{$scan.read::<$t>()};}#[derive(Clone,Copy,PartialEq,Eq,Debug,Default,Hash)]struct P(i64,i64);impl P{fn in_range(self)->bool{L>self.0 as usize && L>self.1 as usize}fn abs(self)->i64{self.0.abs()+self.1.abs()}}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 Mul<i64> for P{type Output=P;fn mul(self,a:i64)->P{P(self.0*a,self.1*a)}}impl Div<i64> for P{type Output=P;fn div(self,a:i64)->P{P(self.0/a,self.1/a)}}impl Neg for P{type Output=P;fn neg(self)->P{P(-self.0,-self.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;}}impl MulAssign<i64> for P{fn mul_assign(&mut self,a:i64){*self=*self*a;}}impl DivAssign<i64> for P{fn div_assign(&mut self,a:i64){*self=*self/a;}}impl<T:Index<usize>> Index<P> for Vec<T>{type Output=T::Output;fn index(&self,idx:P)->&T::Output{&self[idx.0 as usize][idx.1 as usize]}}impl<T:IndexMut<usize>> IndexMut<P> for Vec<T>{fn index_mut(&mut self,idx:P)->&mut T::Output{&mut self[idx.0 as usize][idx.1 as usize]}}const DD:[P;4]=[P(0,-1),P(-1,0),P(0,1),P(1,0)];const DX:[P;8]=[P(0,-1),P(-1,-1),P(-1,0),P(-1,1),P(0,1),P(1,1),P(1,0),P(1,-1)];use std::rc::Rc;#[derive(Clone)]enum List<T>{Cons{v:T,prev:Rc<List<T>>},Nil}use List::*;impl<T:Clone> List<T>{fn restore(&self)->Vec<T>{let mut ret=vec![];let mut ptr=self.clone();while let Cons{v,prev}=ptr{ret.push(v.clone());ptr=(*prev).clone();}ret.reverse();ret}}#[derive(PartialEq,PartialOrd)]struct O<T:PartialEq+PartialOrd>(T);impl<T:PartialEq+PartialOrd> Eq for O<T>{}impl<T:PartialEq+PartialOrd> Ord for O<T>{fn cmp(&self,a:&O<T>)->std::cmp::Ordering{self.0.partial_cmp(&a.0).unwrap()}}struct S<T:PartialEq+PartialOrd,U>(T,U);impl<T:PartialEq+PartialOrd,U> PartialEq for S<T,U>{fn eq(&self,a:&S<T,U>)->bool{self.0.eq(&a.0)}}impl<T:PartialEq+PartialOrd,U> PartialOrd for S<T,U>{fn partial_cmp(&self,a:&S<T,U>)->Option<std::cmp::Ordering>{self.0.partial_cmp(&a.0)}}impl<T:PartialEq+PartialOrd,U> Eq for S<T,U>{}impl<T:PartialEq+PartialOrd,U> Ord for S<T,U>{fn cmp(&self,a:&S<T,U>)->std::cmp::Ordering{self.partial_cmp(a).unwrap()}}