2023-05-25 ガラス戸の修理 / PAST #1 L を解いた
ガラス戸の修理。お金が飛んでいった。
あと 2 問で PAST 本の問題が終わる。 PAST 上級本を買おうか。
neverthrow の ResultAsync を試している。
- PAST #1 L - グラデーション (第一回アルゴリズム実技検定 L問題)
https://atcoder.jp/contests/past201912-open/tasks/past201912_l
- https://atcoder.jp/contests/past201912-open/submissions/41691054
- 最小全域木のコストを求める問題、ただし小さな塔という邪魔がある
- 小さな塔の個数は
M <= 5
と少ないので0..(1 << M)
の範囲で全探索してしまえば良い - あとは対象に含めることを決めた小さな塔と合わせて最小全域木のコストを求めれば良い
use dsu::Dsu;
use proconio::{input, marker::Usize1};
fn main() {
input! {
n: usize,
m: usize,
xyc: [(i64, i64, Usize1); n],
capital_xyc: [(i64, i64, Usize1); m],
}
let mut ans = std::f64::MAX;
for bits in 0_usize..1 << m {
let n = n + bits.count_ones() as usize;
let vertices = xyc
.iter()
.copied()
.chain(
(0..m)
.filter(|i| ((bits >> i) & 1) == 1)
.map(|i| capital_xyc[i]),
)
.collect::<Vec<(i64, i64, usize)>>();
let mut edges = vec![];
for (i, (x_i, y_i, c_i)) in vertices.iter().copied().enumerate() {
for (j, (x_j, y_j, c_j)) in vertices.iter().copied().enumerate() {
if i == j {
continue;
}
let cost = (((x_i - x_j).pow(2) + (y_i - y_j).pow(2)) as f64).sqrt();
edges.push((i, j, cost * if c_i == c_j { 1_f64 } else { 10_f64 }));
}
}
edges.sort_by(|(_, _, a), (_, _, b)| a.partial_cmp(b).unwrap());
let mut sum = 0_f64;
let mut dsu = Dsu::new(n);
for (u, v, c) in edges {
if dsu.same(u, v) {
continue;
}
dsu.merge(u, v);
sum += c;
}
ans = ans.min(sum);
}
println!("{}", ans);
}
// dsu
今日のコミット。
- tsukota 1 commit
- rust-atcoder 1 commit