結果
問題 | No.5007 Steiner Space Travel |
ユーザー | matsu7874 |
提出日時 | 2022-07-30 17:57:22 |
言語 | Rust (1.77.0 + proconio) |
結果 |
AC
|
実行時間 | 11 ms / 1,000 ms |
コード長 | 8,744 bytes |
コンパイル時間 | 2,169 ms |
実行使用メモリ | 2,240 KB |
スコア | 6,840,817 |
最終ジャッジ日時 | 2022-07-30 17:57:32 |
合計ジャッジ時間 | 3,690 ms |
ジャッジサーバーID (参考情報) |
judge12 / judge13 |
純コード判定しない問題か言語 |
(要ログイン)
テストケース
テストケース表示入力 | 結果 | 実行時間 実行使用メモリ |
---|---|---|
testcase_00 | AC | 9 ms
2,004 KB |
testcase_01 | AC | 8 ms
2,172 KB |
testcase_02 | AC | 9 ms
2,104 KB |
testcase_03 | AC | 9 ms
2,160 KB |
testcase_04 | AC | 9 ms
2,240 KB |
testcase_05 | AC | 9 ms
1,984 KB |
testcase_06 | AC | 9 ms
2,032 KB |
testcase_07 | AC | 9 ms
2,172 KB |
testcase_08 | AC | 9 ms
2,116 KB |
testcase_09 | AC | 9 ms
2,180 KB |
testcase_10 | AC | 9 ms
2,064 KB |
testcase_11 | AC | 11 ms
2,104 KB |
testcase_12 | AC | 8 ms
2,036 KB |
testcase_13 | AC | 9 ms
2,108 KB |
testcase_14 | AC | 9 ms
2,080 KB |
testcase_15 | AC | 8 ms
2,216 KB |
testcase_16 | AC | 9 ms
2,128 KB |
testcase_17 | AC | 9 ms
2,188 KB |
testcase_18 | AC | 9 ms
2,176 KB |
testcase_19 | AC | 10 ms
2,160 KB |
testcase_20 | AC | 9 ms
2,148 KB |
testcase_21 | AC | 9 ms
2,060 KB |
testcase_22 | AC | 9 ms
2,120 KB |
testcase_23 | AC | 10 ms
2,004 KB |
testcase_24 | AC | 9 ms
2,052 KB |
testcase_25 | AC | 9 ms
2,152 KB |
testcase_26 | AC | 9 ms
2,184 KB |
testcase_27 | AC | 9 ms
2,232 KB |
testcase_28 | AC | 10 ms
2,096 KB |
testcase_29 | AC | 10 ms
2,132 KB |
コンパイルメッセージ
warning: value assigned to `t` is never read --> Main.rs:7:17 | 7 | let mut t = 0; | ^ | = note: `#[warn(unused_assignments)]` on by default = help: maybe it is overwritten before being read? warning: unused variable: `cluster_ids` --> Main.rs:131:5 | 131 | cluster_ids: &[usize], | ^^^^^^^^^^^ help: if this is intentional, prefix it with an underscore: `_cluster_ids` | = note: `#[warn(unused_variables)]` on by default warning: unused variable: `n` --> Main.rs:253:10 | 253 | let (n, m, planets) = read_input(); | ^ help: if this is intentional, prefix it with an underscore: `_n` warning: 3 warnings emitted
ソースコード
static mut XORSHIFT1: u128 = 123456789; static mut XORSHIFT2: u128 = 362436069; static mut XORSHIFT3: u128 = 521288629; static mut XORSHIFT4: u128 = 88675123; fn xorshift() -> u128 { unsafe { let mut t = 0; t = XORSHIFT1 ^ (XORSHIFT1 << 11u128); XORSHIFT1 = XORSHIFT2; XORSHIFT2 = XORSHIFT3; XORSHIFT3 = XORSHIFT4; XORSHIFT4 = (XORSHIFT4 ^ (XORSHIFT4 >> 19u128)) ^ (t ^ (t >> 8u128)); t } } fn read_input() -> (usize, usize, Vec<(i32, i32)>) { let (n, m) = { let mut s = String::new(); std::io::stdin().read_line(&mut s).unwrap(); let s = s.trim_end().to_owned(); let mut ws = s.split_whitespace(); let n: usize = ws.next().unwrap().parse().unwrap(); let m: usize = ws.next().unwrap().parse().unwrap(); (n, m) }; let mut xy = vec![]; for _ in 0..n { let mut s = String::new(); std::io::stdin().read_line(&mut s).unwrap(); let s = s.trim_end().to_owned(); let mut ws = s.split_whitespace(); let a: i32 = ws.next().unwrap().parse().unwrap(); let b: i32 = ws.next().unwrap().parse().unwrap(); xy.push((a, b)); } (n, m, xy) } const MAX_X: i32 = 1000; type Point = (i32, i32); // fn dist(p: &Point, q: &Point) -> i32 { // (((p.0 - q.0) * (p.0 - q.0) + (p.1 - q.1) * (p.1 - q.1)) as f64).sqrt() as i32 // } fn dist_powered(p: &Point, q: &Point) -> i32 { (p.0 - q.0) * (p.0 - q.0) + (p.1 - q.1) * (p.1 - q.1) } fn kmeans(points: &[Point], k: usize, max_iter: usize) -> (Vec<Point>, Vec<usize>) { let n = points.len(); let mut centors = Vec::with_capacity(k); for _ in 0..k { centors.push(( (xorshift() as i32).abs() % (MAX_X + 1), (xorshift() as i32).abs() % (MAX_X + 1), )); } let mut cluster_ids = vec![0; n]; let mut cluster_sizes = vec![0; k]; cluster_sizes[0] = n as i32; let mut updated = false; for loop_count in 0..max_iter { // 各点から最も近い代表点を探す for i in 0..n { let mut nearest_centor_id = 0; let mut nearest_centor_distance = dist_powered(&points[i], ¢ors[0]); for j in 1..k { let distance = dist_powered(&points[i], ¢ors[j]); if distance < nearest_centor_distance { nearest_centor_distance = distance; nearest_centor_id = j; } } if nearest_centor_id != cluster_ids[i] { cluster_sizes[cluster_ids[i]] -= 1; cluster_ids[i] = nearest_centor_id; cluster_sizes[nearest_centor_id] += 1; updated = true; } } // 代表点の座標をクラスタの中心に移動する let mut dxs = vec![0; k]; let mut dys = vec![0; k]; for i in 0..n { let cid = cluster_ids[i]; dxs[cid] += points[i].0 - centors[cid].0; dys[cid] += points[i].1 - centors[cid].1; } for i in 0..k { if cluster_sizes[i] == 0 { continue; } centors[i].0 += dxs[i] / cluster_sizes[i]; centors[i].1 += dys[i] / cluster_sizes[i]; } if !updated { eprintln!("kmeans loop breaked at loop {}", loop_count); break; } } (centors, cluster_ids) } // fn tsp_dp(points:&[Point])->Vec<usize>{ // let n = points.len(); // let mut dp = vec![] // } const ALPHA: i32 = 5; fn get_cost_coefficient(t1: usize, t2: usize) -> i32 { if t1 == PLANET { if t2 == PLANET { ALPHA * ALPHA } else { ALPHA } } else { if t2 == PLANET { ALPHA } else { 1 } } } const PLANET: usize = 1; const STATION: usize = 2; fn search_path( stations: &[Point], planets: &[Point], cluster_ids: &[usize], ) -> Vec<(usize, usize)> { let n = planets.len(); let m = stations.len(); // 全点対の最短経路を求める let mut next = vec![vec![0; n + m]; n + m]; for i in 0..n + m { for j in 0..n + m { next[i][j] = j; } } let mut dist = vec![vec![i32::MAX / 4; n + m]; n + m]; for i in 0..n + m { let p = if i < n { planets[i] } else { stations[i - n] }; let tp = if i < n { PLANET } else { STATION }; for j in 0..n + m { let q = if j < n { planets[j] } else { stations[j - n] }; let tq = if i < n { PLANET } else { STATION }; dist[i][j] = get_cost_coefficient(tp, tq) * dist_powered(&p, &q); } } for k in 0..n + m { for i in 0..n + m { for j in 0..n + m { if dist[i][k] + dist[k][j] < dist[i][j] { dist[i][j] = dist[i][k] + dist[k][j]; next[i][j] = next[i][k]; } } } } // 経路を作成する let mut path = vec![(PLANET, 0)]; let mut visited = vec![false; planets.len()]; visited[0] = true; let mut count_visited_planets = 1; let mut cur_id = 0; while count_visited_planets < planets.len() { // まだ到達していない惑星のなかで距離が最小のものに移動する let mut nearest_distance = i32::MAX; let mut nearest = (PLANET, 0); for i in 0..planets.len() { if visited[i] { continue; } // let distance = // get_cost_coefficient(cur_type, PLANET) * dist_powered(&cur_point, &planets[i]); if dist[cur_id][i] < nearest_distance { nearest_distance = dist[cur_id][i]; nearest = (PLANET, i); } } // 経路に追加する if nearest.0 == PLANET { count_visited_planets += 1; visited[nearest.1] = true; // 経路復元 let mut cur = cur_id; while cur != nearest.1 { cur = next[cur][nearest.1]; path.push((if cur < n { PLANET } else { STATION }, cur % n)); } } path.push(nearest); cur_id = nearest.1; } // planet0に帰る let mut cur = cur_id; while cur != 0 { cur = next[cur][0]; path.push((if cur < n { PLANET } else { STATION }, cur % n)); } let path_len = path.len(); fn get_cost( planets: &[Point], stations: &[Point], a: (usize, usize), b: (usize, usize), ) -> i32 { get_cost_coefficient(a.0, b.0) * dist_powered( if a.0 == PLANET { &planets[a.1] } else { &stations[a.1] }, if b.0 == PLANET { &planets[b.1] } else { &stations[b.1] }, ) } // 2-pot for _ in 0..50000 { let i = xorshift() as usize % (path_len - 1); let j = xorshift() as usize % (path_len - 1); let a = path[i]; let b = path[i + 1]; let c = path[j]; let d = path[j + 1]; let origi_dist = get_cost(planets, stations, a, b) + get_cost(planets, stations, c, d); let new_dist = get_cost(planets, stations, a, d) + get_cost(planets, stations, b, c); if new_dist < origi_dist { let swap_count = ((j as f32 - (i + 1) as f32) / 2.0 + 0.5) as usize; for offset in 0..swap_count { path.swap((i + 1 + offset) % path_len, (j - offset) % path_len); } } } path } fn main() { let (n, m, planets) = read_input(); let (stations, cluster_ids) = kmeans(&planets, m, 1000); eprintln!("stations: {:?}", stations); let path = search_path(&stations, &planets, &cluster_ids); assert!(path.len() <= 100000); for (x, y) in stations.iter() { println!("{} {}", x, y); } println!("{}", path.len()); for (t, i) in path.iter() { println!("{} {}", t, i + 1); } } #[cfg(test)] mod tests { use super::*; #[test] fn test_kmeans() { let points = vec![(10, 10), (1000, 1000), (10, 5), (10, 6)]; let (centors, cluster_id) = kmeans(&points, 2, 100); eprintln!("centors:{:?}", centors); eprintln!("cluster_id:{:?}", cluster_id); assert_eq!(cluster_id[0], cluster_id[2]); assert_eq!(cluster_id[0], cluster_id[3]); assert_eq!(centors[cluster_id[0]], (10, 7)); assert_eq!(centors[cluster_id[1]], (1000, 1000)); } }