結果
問題 | No.5020 Averaging |
ユーザー |
![]() |
提出日時 | 2024-02-25 17:35:08 |
言語 | Rust (1.83.0 + proconio) |
結果 |
AC
|
実行時間 | 277 ms / 1,000 ms |
コード長 | 7,683 bytes |
コンパイル時間 | 1,409 ms |
コンパイル使用メモリ | 191,340 KB |
実行使用メモリ | 25,492 KB |
スコア | 23,767,175 |
最終ジャッジ日時 | 2024-02-25 17:35:28 |
合計ジャッジ時間 | 15,328 ms |
ジャッジサーバーID (参考情報) |
judge14 / judge10 |
純コード判定しない問題か言語 |
(要ログイン)
ファイルパターン | 結果 |
---|---|
other | AC * 50 |
コンパイルメッセージ
warning: unnecessary parentheses around assigned value --> Main.rs:151:22 | 151 | nijou += (aa * aa + bb * bb); | ^ ^ | = note: `#[warn(unused_parens)]` on by default help: remove these parentheses | 151 - nijou += (aa * aa + bb * bb); 151 + nijou += aa * aa + bb * bb; | warning: 1 warning emitted
ソースコード
#![allow(non_snake_case)]#![allow(dead_code)]#![allow(unused_imports)]#![allow(unused_variables)]#![allow(unused_mut)]#![allow(non_upper_case_globals)]//proconiomacro_rules! input {(source = $s:expr, $($r:tt)*) => {let mut iter = $s.split_whitespace();input_inner!{iter, $($r)*}};($($r:tt)*) => {let mut s = {use std::io::Read;let mut s = String::new();std::io::stdin().read_to_string(&mut s).unwrap();s};let mut iter = s.split_whitespace();input_inner!{iter, $($r)*}};}macro_rules! input_inner {($iter:expr) => {};($iter:expr, ) => {};($iter:expr, $var:ident : $t:tt $($r:tt)*) => {let $var = read_value!($iter, $t);input_inner!{$iter $($r)*}};}macro_rules! read_value {($iter:expr, ( $($t:tt),* )) => {( $(read_value!($iter, $t)),* )};($iter:expr, [ $t:tt ; $len:expr ]) => {(0..$len).map(|_| read_value!($iter, $t)).collect::<Vec<_>>()};($iter:expr, chars) => {read_value!($iter, String).chars().collect::<Vec<char>>()};($iter:expr, usize1) => {read_value!($iter, usize) - 1};($iter:expr, $t:ty) => {$iter.next().unwrap().parse::<$t>().expect("Parse error")};}const mokuhyou: usize = 500000000000000000;const n: usize = 45;use std::cmp::Ordering;use std::cmp::{Eq, Ord, PartialEq, PartialOrd};use std::collections::BinaryHeap;const WID: usize = 50;const CHA: usize = 100;const keta: usize = 100000000000000000;pub fn get_time() -> f64 {static mut STIME: f64 = -1.0; // 初期値let t = std::time::SystemTime::now() // nowを取得.duration_since(std::time::UNIX_EPOCH).unwrap();// a.duration_since(b)だとa>bが前提let ms = t.as_secs() as f64 + t.subsec_nanos() as f64 * 1e-9;// as_secsが秒, .subsec_nanos()が小数点以下の秒unsafe {if STIME < 0.0 {STIME = ms; // 経過時間の初期化}// ローカル環境とジャッジ環境の実行速度差はget_timeで吸収しておくと便利#[cfg(feature = "local")]{(ms - STIME) * 1.3}#[cfg(not(feature = "local"))]{ms - STIME}}}fn main() {get_time();input! {nn:usize, XY:[(usize,usize);n]}let inp = Input { XY };let mut rng = Xorshift::new(20250225);// eprintln!("XY {:?}", &inp.XY);let bestboard = beam_search(&inp, &mut rng, WID, CHA);bestboard.printstate();eprintln!("{}",bestboard.nowval[0].0.abs_diff(mokuhyou) + bestboard.nowval[0].1.abs_diff(mokuhyou));eprintln!("time {}", get_time());eprintln!("cost {}", bestboard.cost);}struct Xorshift {val: usize,}impl Xorshift {fn new(seed: usize) -> Self {let mut hoge = seed;hoge ^= seed << 17;hoge ^= seed >> 13;hoge ^= seed << 5;Xorshift { val: hoge }}fn next(&mut self) {let hoge = self.val;self.val ^= hoge << 17;self.val ^= hoge >> 13;self.val ^= hoge << 5;}fn rand(&mut self) -> f64 {self.next();(self.val / std::usize::MAX) as f64}fn randint(&mut self, a: usize, b: usize) -> usize {self.next();self.val % (b - a) + a}}struct Input {XY: Vec<(usize, usize)>,}#[derive(Clone)]// #[derive(Debug, PartialEq, PartialOrd, Eq)]struct Board {orders: Vec<(usize, usize)>,nowval: Vec<(usize, usize)>,goukei: f64,nijou: f64,cost: f64,}impl Board {fn new(inp: &Input) -> Self {let mut goukei = 0.0;let mut nijou = 0.0;for &(a, b) in inp.XY.iter() {let aa = a as f64 / keta as f64;let bb = b as f64 / keta as f64;goukei += aa + bb;nijou += (aa * aa + bb * bb);}Self {orders: vec![],nowval: inp.XY.clone(),goukei,nijou,cost: std::f64::MAX,}}fn action(&mut self, a: usize, b: usize, rng: &mut Xorshift) {// eprintln!("a b {} {}", a, b);assert!(a != b);let n1 = self.nowval[a].0;let n2 = self.nowval[a].1;let n3 = self.nowval[b].0;let n4 = self.nowval[b].1;let v1 = (n1 + n3) / 2;let v2 = (n2 + n4) / 2;self.nowval[a] = (v1, v2);self.nowval[b] = (v1, v2);self.orders.push((a + 1, b + 1));let nn1 = n1 as f64 / keta as f64;let nn2 = n2 as f64 / keta as f64;let nn3 = n3 as f64 / keta as f64;let nn4 = n4 as f64 / keta as f64;let vv1 = (nn1 + nn3) / 2.0;let vv2 = (nn2 + nn4) / 2.0;self.nijou +=2.0 * (vv1 * vv1 + vv2 * vv2) - (nn1 * nn1 + nn2 * nn2 + nn3 * nn3 + nn4 * nn4);self.calccost(rng);}fn calccost(&mut self, rng: &mut Xorshift) {let std = self.nijou / (n as f64 * n as f64)- (self.goukei as f64 / n as f64) * (self.goukei as f64 / n as f64);self.cost = (mokuhyou.abs_diff(self.nowval[0].0) + mokuhyou.abs_diff(self.nowval[0].1))as f64- 1.0 * std;// self.cost = (mokuhyou.abs_diff(self.nowval[0].0) + mokuhyou.abs_diff(self.nowval[0].1))// as f64// + rng.rand();}fn printstate(&self) {println!("{}", self.orders.len());for &(a, b) in self.orders.iter() {println!("{} {}", a, b);}}}// 順序関係を作る。impl Ord for Board {fn cmp(&self, other: &Self) -> Ordering {other.partial_cmp(self).unwrap_or(Ordering::Equal)}}impl PartialEq for Board {fn eq(&self, other: &Self) -> bool {self.cost == other.cost}}impl Eq for Board {} // ここは空でOKimpl PartialOrd for Board {fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {other.cost.partial_cmp(&self.cost)}}fn beam_search(inp: &Input, rng: &mut Xorshift, beam_width: usize, challenge_time: usize) -> Board {let mut board = Board::new(inp);let mut preheap = BinaryHeap::new();let mut nexheap = BinaryHeap::new();board.calccost(rng);let mut bestboard = board.clone();preheap.push(board);for turn in 0..50 {eprintln!("turn {}", turn);eprintln!("size {}", preheap.len());for __ in 0..beam_width {if preheap.is_empty() {break;}// eprintln!("pre");let mut preboard = preheap.pop().unwrap();for ___ in 0..challenge_time {let mut nexboard = preboard.clone();let idx1 = rng.randint(0, n - 1);let idx2 = rng.randint(idx1 + 1, n);nexboard.action(idx1, idx2, rng);nexheap.push(nexboard);let mut nexboard = preboard.clone();let idx1 = rng.randint(1, n);nexboard.action(0, idx1, rng);nexheap.push(nexboard);}}preheap.clear();for _ in 0..beam_width {if nexheap.is_empty() {break;}// eprintln!("nex");let mut board = nexheap.pop().unwrap();if board.cost < bestboard.cost {eprintln!("best");bestboard = board.clone();}preheap.push(board);}nexheap.clear()}bestboard}