Submission #68242799


Source Code Expand

use rand::{rngs::ThreadRng, Rng};
use std::{
    cmp::{max, min},
    collections::HashMap,
    time::Instant,
};

#[derive(Debug, Clone)]
struct Separator {
    id: usize,
    effect: Vec<f64>,
    effect_inv: Vec<f64>,
}

impl Separator {
    fn new() -> Self {
        Separator {
            id: 0,
            effect: Vec::new(),
            effect_inv: Vec::new(),
        }
    }
}

#[derive(Debug, Clone)]
enum To {
    To0,
    To1,
}
#[derive(Debug, Clone)]
struct Context {
    n: usize,
    m: usize,
    k: usize,
    space_for_disposers: Vec<(i64, i64)>,
    space_for_separators: Vec<(i64, i64)>,
    separators: HashMap<usize, Separator>,
    best_separator_cache: Vec<(usize, To)>,
}

impl Context {
    fn new() -> Self {
        Context {
            n: 0,
            m: 0,
            k: 0,
            space_for_disposers: Vec::new(),
            space_for_separators: Vec::new(),
            separators: HashMap::new(),
            best_separator_cache: Vec::new(),
        }
    }
    fn input() -> Self {
        let mut context = Context::new();

        //input
        let mut s: String = String::new();
        std::io::stdin().read_line(&mut s).ok();
        let v: Vec<u64> = s
            .trim()
            .split_whitespace()
            .map(|e| e.parse().ok().unwrap())
            .collect();

        context.n = v[0] as usize;
        context.m = v[1] as usize;
        context.k = v[2] as usize;

        for _ in 0..context.n {
            let mut s: String = String::new();
            std::io::stdin().read_line(&mut s).ok();
            let v: Vec<u64> = s
                .trim()
                .split_whitespace()
                .map(|e| e.parse().ok().unwrap())
                .collect();
            let x = v[0];
            let y = v[1];
            context.space_for_disposers.push((x as i64, y as i64));
        }

        for _ in 0..context.m {
            let mut s: String = String::new();
            std::io::stdin().read_line(&mut s).ok();
            let v: Vec<u64> = s
                .trim()
                .split_whitespace()
                .map(|e| e.parse().ok().unwrap())
                .collect();
            let x = v[0];
            let y = v[1];
            context.space_for_separators.push((x as i64, y as i64));
        }

        for i in 0..context.k {
            let mut s: String = String::new();
            std::io::stdin().read_line(&mut s).ok();
            let v: Vec<f64> = s
                .trim()
                .split_whitespace()
                .map(|e| e.parse().ok().unwrap())
                .collect();
            let mut separator = Separator::new();
            for j in 0..context.n {
                separator.id = i;
                separator.effect.push(v[j as usize]);
                separator.effect_inv.push(1.0 - v[j as usize]);
            }
            context.separators.insert(i, separator);
        }

        context.best_separator_cache = vec![(0, To::To0); context.n];
        let mut ratio_memo = vec![0.0; context.n];
        for key in context.separators.keys() {
            let ratio = get_ratios(&context.separators.get(&key).unwrap().effect);
            for index in 0..context.n {
                if ratio[index] > ratio_memo[index] {
                    ratio_memo[index] = ratio[index];
                    context.best_separator_cache[index] = (*key, To::To0);
                }
            }

            let ratio = get_ratios(&context.separators.get(&key).unwrap().effect_inv);
            for index in 0..context.n {
                if ratio[index] > ratio_memo[index] {
                    ratio_memo[index] = ratio[index];
                    context.best_separator_cache[index] = (*key, To::To1);
                }
            }
        }

        return context;
    }
}

#[derive(Debug, Clone, PartialEq, Eq)]
enum TargetKind {
    Separator,
    Disposer,
}

#[derive(Debug, Clone)]
struct Target {
    target_kind: TargetKind,
    target_id: usize,
}

impl Target {
    fn format(&self, context: &Context) -> usize {
        match self.target_kind {
            TargetKind::Disposer => self.target_id,
            TargetKind::Separator => context.n + self.target_id,
        }
    }

    fn position(&self, context: &Context) -> (i64, i64) {
        match self.target_kind {
            TargetKind::Disposer => context.space_for_disposers[self.target_id],
            TargetKind::Separator => context.space_for_separators[self.target_id],
        }
    }
}

#[derive(Debug, Clone)]
struct SeparatorLayout {
    separator_id: usize,
    to0: Target,
    to1: Target,
}

#[derive(Debug, Clone)]
struct Answer {
    disposer_layout: Vec<usize>,
    init_target: Target,
    separator_layout: HashMap<usize, SeparatorLayout>,
}

impl Answer {
    fn print(&self, context: &Context) {
        for i in 0..self.disposer_layout.len() {
            print!("{0} ", self.disposer_layout[i])
        }
        println!();

        println!("{0}", self.init_target.format(context));

        for i in 0..context.m {
            match self.separator_layout.get(&i) {
                Some(x) => println!(
                    "{0} {1} {2}",
                    x.separator_id,
                    x.to0.format(context),
                    x.to1.format(context)
                ),
                None => println!("-1"),
            }
        }
    }

    fn check_and_insert_separator_layout(
        &mut self,
        context: &Context,
        target: usize,
        layout: SeparatorLayout,
        dryrun: bool,
    ) -> bool {
        // insertできたらtrue
        // separator_layoutは基本的にこのメソッドで追加する

        let mut edges = vec![];
        let start_point = (0, 5000);
        if self.init_target.target_id != 10000000 {
            let init_target = self.init_target.position(context);
            edges.push((start_point, init_target));
        }

        for key in self.separator_layout.keys() {
            if *key == target {
                continue;
            }
            let start = context.space_for_separators[*key];
            let separator_layout = self.separator_layout.get(key).unwrap();

            edges.push((start, separator_layout.to0.position(context)));

            edges.push((start, separator_layout.to1.position(context)));
        }

        let new_edge0 = (
            context.space_for_separators[target],
            layout.to0.position(context),
        );
        let new_edge1 = (
            context.space_for_separators[target],
            layout.to1.position(context),
        );

        let mut seen: HashMap<usize, bool> = HashMap::new();
        let mut finished: HashMap<usize, bool> = HashMap::new();

        // 閉路検出
        fn has_closed_circle(
            new_taregt: usize,
            new_target_layout: &SeparatorLayout,
            current: &Target,
            answer: &Answer,
            context: &Context,
            seen: &mut HashMap<usize, bool>,
            finished: &mut HashMap<usize, bool>,
        ) -> bool {
            seen.insert(current.format(context), true);

            if current.target_kind == TargetKind::Disposer {
                finished.insert(current.format(context), true);
                return false;
            }

            let target = match new_taregt == current.target_id {
                true => new_target_layout,
                false => {
                    // 初期配置の場合は判定対象外
                    if answer.separator_layout.keys().len() == 0 {
                        return false;
                    }
                    answer.separator_layout.get(&current.target_id).unwrap()
                }
            };

            if !finished.contains_key(&target.to0.format(context)) {
                if seen.contains_key(&target.to0.format(context)) {
                    return true;
                }

                if has_closed_circle(
                    new_taregt,
                    &new_target_layout,
                    &target.to0,
                    answer,
                    context,
                    seen,
                    finished,
                ) {
                    return true;
                }
            }
            if !finished.contains_key(&target.to1.format(context)) {
                if seen.contains_key(&target.to1.format(context)) {
                    return true;
                }
                if has_closed_circle(
                    new_taregt,
                    &new_target_layout,
                    &target.to1,
                    answer,
                    context,
                    seen,
                    finished,
                ) {
                    return true;
                }
            }

            finished.insert(current.format(context), true);
            return false;
        }

        if has_closed_circle(
            target,
            &layout,
            &self.init_target,
            &self,
            context,
            &mut seen,
            &mut finished,
        ) {
            return false;
        }
        for key in self.separator_layout.keys() {
            if has_closed_circle(
                target,
                &layout,
                &Target {
                    target_kind: TargetKind::Separator,
                    target_id: *key,
                },
                &self,
                context,
                &mut seen,
                &mut finished,
            ) {
                return false;
            }
        }

        if check_cross(new_edge0, &edges) | check_cross(new_edge1, &edges) {
            return false;
        } else {
            if !dryrun {
                self.separator_layout.insert(target, layout);
            }
            return true;
        }
    }

    fn remove_unnecessary_edges(&mut self, context: &Context) {
        // その先にdiaposerがない場合、そのseparatorを取り除く
        let mut remove_separator_list = vec![];
        for key in self.separator_layout.keys() {
            if !self.separator_has_diposer(*key, context) {
                remove_separator_list.push(*key);
            }
        }

        for x in remove_separator_list {
            self.separator_layout.remove(&x);
        }

        // separatorに接続されていない辺はもう一つの辺に統合する
        let mut integration_list = vec![];
        for key in self.separator_layout.keys() {
            let layout = self.separator_layout.get(&key).unwrap();
            if layout.to1.target_kind == TargetKind::Separator
                && !self.separator_layout.contains_key(&layout.to1.target_id)
            {
                integration_list.push(*key);
            }
        }
        for x in integration_list {
            let layout = self.separator_layout.get(&x).unwrap();
            self.separator_layout.insert(
                x,
                SeparatorLayout {
                    separator_id: layout.separator_id,
                    to0: layout.to0.clone(),
                    to1: layout.to0.clone(),
                },
            );
        }
    }

    // そのseparatorより先に一つでもdisposerがあるか
    fn separator_has_diposer(&self, target_id: usize, context: &Context) -> bool {
        if !self.separator_layout.contains_key(&target_id) {
            return false;
        }

        if self
            .separator_layout
            .get(&target_id)
            .unwrap()
            .to0
            .target_kind
            == TargetKind::Disposer
            || self
                .separator_layout
                .get(&target_id)
                .unwrap()
                .to1
                .target_kind
                == TargetKind::Disposer
        {
            return true;
        }

        return self
            .separator_has_diposer(self.separator_layout[&target_id].to0.target_id, context)
            || self
                .separator_has_diposer(self.separator_layout[&target_id].to1.target_id, context);
    }

    fn score(&self, context: &Context) -> u64 {
        let mut ratio = vec![vec![0.0; context.n]; context.n];

        fn add_ratio(
            answer: &Answer,
            ans_ratio: &mut Vec<Vec<f64>>,
            target: &Target,
            input_ratio: Vec<f64>,
            context: &Context,
        ) {
            if target.target_kind == TargetKind::Disposer {
                let target_disposer = answer.disposer_layout[target.target_id];
                for i in 0..context.n {
                    ans_ratio[target_disposer][i] += input_ratio[i];
                }
                return;
            }

            let target_separator = answer.separator_layout.get(&target.target_id).unwrap();

            add_ratio(
                answer,
                ans_ratio,
                &target_separator.to0,
                hadamard_product(
                    &input_ratio,
                    &context
                        .separators
                        .get(&target_separator.separator_id)
                        .unwrap()
                        .effect,
                ),
                context,
            );
            add_ratio(
                answer,
                ans_ratio,
                &target_separator.to1,
                hadamard_product(
                    &input_ratio,
                    &context
                        .separators
                        .get(&target_separator.separator_id)
                        .unwrap()
                        .effect_inv,
                ),
                context,
            );
        }

        add_ratio(
            self,
            &mut ratio,
            &self.init_target,
            vec![1.0; context.n],
            context,
        );

        let mut score = 0;
        for i in 0..context.n {
            score += (1000000000.0 * (1.0 - ratio[i][i]) / (context.n as f64)) as u64;
        }

        return score;
    }

    fn new() -> Self {
        return {
            Answer {
                disposer_layout: Vec::new(),
                init_target: Target {
                    target_kind: TargetKind::Separator,
                    target_id: 10000000,
                },
                separator_layout: HashMap::new(),
            }
        };
    }
}

fn sign(x: i64) -> i64 {
    if x > 0 {
        return 1;
    } else {
        if x < 0 {
            return -1;
        } else {
            return 0;
        }
    }
}

fn orientation(a: (i64, i64), b: (i64, i64), c: (i64, i64)) -> i64 {
    let cross = (b.0 - a.0) * (c.1 - a.1) - (b.1 - a.1) * (c.0 - a.0);
    return sign(cross);
}

fn segments_intersect(edge0: ((i64, i64), (i64, i64)), edge1: ((i64, i64), (i64, i64))) -> bool {
    let p1 = edge0.0;
    let p2 = edge0.1;
    let q1 = edge1.0;
    let q2 = edge1.1;

    if p1 == q1 || p1 == q2 {
        return false;
    }
    if p2 == q1 || p2 == q2 {
        return false;
    }

    if (max(p1.0, p2.0) < min(q1.0, q2.0))
        | (max(q1.0, q2.0) < min(p1.0, p2.0))
        | (max(p1.1, p2.1) < min(q1.1, q2.1))
        | (max(q1.1, q2.1) < min(p1.1, p2.1))
    {
        return false;
    }

    let o1 = orientation(p1, p2, q1);
    let o2 = orientation(p1, p2, q2);
    let o3 = orientation(q1, q2, p1);
    let o4 = orientation(q1, q2, p2);

    return (o1 * o2 <= 0) & (o3 * o4 <= 0);
}

fn check_cross(edge: ((i64, i64), (i64, i64)), edges: &Vec<((i64, i64), (i64, i64))>) -> bool {
    for e in edges {
        if segments_intersect(edge, *e) {
            return true;
        }
    }
    return false;
}

fn calc_group(position: (i64, i64)) -> usize {
    let x_index = position.0 > 5000;
    let y_index = position.1 > 5000;

    let mut num = 0;
    if x_index {
        num += 2;
    }
    if y_index {
        num += 1;
    }
    return num;
}

fn init_result(context: &Context) -> Answer {
    let mut answer = Answer::new();

    // 上半分で一番を近いところを始点とする
    let mut nearest_space_from_start = 0;
    let mut distance: i64 = 20000 * 20000;
    for space_for_separator in 0..context.m {
        // 使用済みの場合はSKIP
        if answer.separator_layout.contains_key(&space_for_separator) {
            continue;
        }

        let position = context.space_for_separators[space_for_separator];
        let start_point = (0, 5000);

        if position.1 < 5000 {
            continue;
        }

        let d = distance_squared(&position, &start_point);
        if d < distance {
            distance = d;
            nearest_space_from_start = space_for_separator;
        }
    }

    // 上半分になかった場合はyが一番小さいところにする
    if distance == 20000 * 20000 {
        let mut smallest_y: i64 = 10001;
        for space_for_separator in answer.separator_layout.keys() {
            if answer.separator_layout.contains_key(space_for_separator) {
                continue;
            }
            let position = context.space_for_separators[*space_for_separator];

            if position.1 < smallest_y {
                smallest_y = position.1;
                nearest_space_from_start = *space_for_separator;
            }
        }
    }

    answer.init_target = Target {
        target_kind: TargetKind::Separator,
        target_id: nearest_space_from_start,
    };

    // x: 0~5000, 5001~10000, y: 0~5000, 5001~10000 で四つに分類
    // 1 3
    // 0 2
    // 1 -> 3 -> 2 -> 0 の順につなぐ
    let mut space_for_disposer_by_group = vec![vec![]; 4];
    for i in 0..context.n {
        // 適当にdisposerを配置する
        answer.disposer_layout.push(i);
        let target = context.space_for_disposers[i];
        let num = calc_group(target);

        space_for_disposer_by_group[num].push(i);
    }

    // 1 -> 3 -> 2 -> 0 の順につなぐ
    // 1: xの昇順
    space_for_disposer_by_group[1].sort_by(|a, b| {
        context.space_for_disposers[*a]
            .0
            .cmp(&context.space_for_disposers[*b].0)
    });
    // 3: xの昇順
    space_for_disposer_by_group[3].sort_by(|a, b| {
        context.space_for_disposers[*a]
            .0
            .cmp(&context.space_for_disposers[*b].0)
    });
    // 0: xの降順
    space_for_disposer_by_group[0].sort_by(|a, b| {
        context.space_for_disposers[*b]
            .0
            .cmp(&context.space_for_disposers[*a].0)
    });
    // 2: xの降順
    space_for_disposer_by_group[2].sort_by(|a, b| {
        context.space_for_disposers[*b]
            .0
            .cmp(&context.space_for_disposers[*a].0)
    });

    let mut all_disposers = Vec::new();
    all_disposers.append(&mut space_for_disposer_by_group[1]);
    all_disposers.append(&mut space_for_disposer_by_group[3]);
    all_disposers.append(&mut space_for_disposer_by_group[2]);
    all_disposers.append(&mut space_for_disposer_by_group[0]);

    let mut nearest_separators_and_output = vec![];

    // 各disposerについて、未使用で最寄りのseparatorに配置する
    // 一番最初はinitと接続する
    let mut init_complete = false;
    for i in 0..all_disposers.len() {
        let disposer = answer.disposer_layout[all_disposers[i]];

        let mut nearest_space_for_separator = 0;
        let mut distance = 100000 * 100000;

        for j in 0..context.m {
            if answer.init_target.target_kind == TargetKind::Separator
                && answer.init_target.target_id == j
            {
                continue;
            }
            if answer.separator_layout.contains_key(&j) {
                continue;
            }

            let space_for_separator = context.space_for_separators[j];
            let d = distance_squared(&context.space_for_disposers[disposer], &space_for_separator);
            if d < distance {
                distance = d;
                nearest_space_for_separator = j;
            }
        }

        if distance == 100000 * 100000 {
            continue;
        }

        let (separator_id, output) = context.best_separator_cache[disposer].clone();
        let layout = SeparatorLayout {
            separator_id: separator_id,
            to0: Target {
                target_kind: TargetKind::Disposer,
                target_id: disposer,
            },
            to1: Target {
                target_kind: TargetKind::Disposer,
                target_id: disposer,
            },
        };

        let put = answer.check_and_insert_separator_layout(
            context,
            nearest_space_for_separator,
            layout,
            false,
        );
        if put {
            nearest_separators_and_output.push((nearest_space_for_separator, output));
        }

        if put && !init_complete {
            let put = answer.check_and_insert_separator_layout(
                context,
                nearest_space_from_start,
                SeparatorLayout {
                    separator_id: 0, // 適当
                    to0: Target {
                        target_kind: TargetKind::Separator,
                        target_id: nearest_space_for_separator,
                    },
                    to1: Target {
                        target_kind: TargetKind::Separator,
                        target_id: nearest_space_for_separator,
                    },
                },
                false,
            );
            if put {
                init_complete = true;
            }
        }
    }

    for i in 1..nearest_separators_and_output.len() {
        // 一つ前のseparatorを接続する
        let (separator, output) = &nearest_separators_and_output[i - 1];
        let mut layout = answer.separator_layout.get(separator).unwrap().clone();

        match output {
            To::To0 => {
                layout.to1 = Target {
                    target_kind: TargetKind::Separator,
                    target_id: nearest_separators_and_output[i].0,
                }
            }
            To::To1 => {
                layout.to0 = Target {
                    target_kind: TargetKind::Separator,
                    target_id: nearest_separators_and_output[i].0,
                }
            }
        }

        answer.check_and_insert_separator_layout(context, *separator, layout, false);
    }

    return answer;
}

fn main() {
    let start = Instant::now();

    let context = Context::input();

    let init_result = init_result(&context);

    let result = anealing(&init_result, &start, &context);
    result.print(&context);
}

fn distance_squared(a: &(i64, i64), b: &(i64, i64)) -> i64 {
    return (a.0 - b.0) * (a.0 - b.0) + (a.1 - b.1) * (a.1 - b.1);
}

#[allow(dead_code)]
fn make_hadamard_product(separators_matrix: &Vec<Vec<f64>>, indexes: &Vec<usize>) -> Vec<f64> {
    if indexes.len() == 0 {
        return vec![];
    }

    let mut v = separators_matrix[indexes[0]].clone();

    for i in 1..indexes.len() {
        v = hadamard_product(&v, &separators_matrix[indexes[i]]);
    }

    return v;
}

fn hadamard_product(a: &Vec<f64>, b: &Vec<f64>) -> Vec<f64> {
    assert_eq!(a.len(), b.len());
    let mut v = vec![0.0; a.len()];
    for i in 0..a.len() {
        v[i] = a[i] * b[i];
    }
    return v;
}

#[allow(dead_code)]
fn average(a: &Vec<f64>) -> f64 {
    assert_ne!(a.len(), 0);

    let mut sum = 0.0;
    for i in 0..a.len() {
        sum += a[i];
    }
    return sum / a.len() as f64;
}

#[allow(dead_code)]
fn variance(a: &Vec<f64>) -> f64 {
    let ave = average(a);

    let mut diff_sum = 0.0;
    for i in 0..a.len() {
        diff_sum += (a[i] - ave).abs();
    }

    return diff_sum / a.len() as f64;
}

#[allow(dead_code)]
fn get_ratios(a: &Vec<f64>) -> Vec<f64> {
    assert_ne!(a.len(), 0);

    let mut sum = 0.0;
    for i in 0..a.len() {
        sum += a[i];
    }

    let mut v = vec![0.0; a.len()];

    for i in 0..a.len() {
        v[i] = a[i] / sum;
    }

    return v;
}

fn anealing(answer: &Answer, start_time: &Instant, context: &Context) -> Answer {
    let mut new_ans = answer.clone();

    let time_limit = 1950;

    let start_temp = 1e9;
    let end_temp = 1e2;

    let mut rng = rand::thread_rng();

    let mut update_counter = 0;
    let mut iteration = 0;

    while start_time.elapsed().as_millis() < time_limit {
        let elapsed = start_time.elapsed().as_millis();
        let temp = start_temp - (start_temp - end_temp) * (elapsed / time_limit) as f64;

        let neibourhood = make_neighbourhood(&new_ans, &mut rng, context);

        let score_diff = neibourhood.score(context) - new_ans.score(context);

        let prob = (score_diff as f64 / temp).exp();

        if prob > rng.gen_range(0.0..1.0) {
            new_ans = neibourhood;
            update_counter += 1;
        }
        iteration += 1;
    }
    dbg!(iteration, update_counter);
    return new_ans;
}

fn make_neighbourhood(answer: &Answer, rng: &mut ThreadRng, context: &Context) -> Answer {
    let target = rng.gen_range(0..2);

    // 0: separatorをまだseparatorがない場所に適当に置き、separatorもしくはdisposerに接続する
    if target == 0 {
        let mut separator_candidate = Vec::new();
        let mut destination_candidate = Vec::new();

        for i in 0..context.m {
            if answer.separator_layout.contains_key(&i) {
                destination_candidate.push(Target {
                    target_kind: TargetKind::Separator,
                    target_id: i,
                });
            } else {
                separator_candidate.push(i);
            }
        }
        for i in 0..context.n {
            destination_candidate.push(Target {
                target_kind: TargetKind::Disposer,
                target_id: i,
            });
        }

        if separator_candidate.len() == 0 || destination_candidate.len() == 0 {
            return answer.clone();
        }
        let separator = separator_candidate[rng.gen_range(0..separator_candidate.len())];
        let t0 = &destination_candidate[rng.gen_range(0..destination_candidate.len())];
        let t1 = &destination_candidate[rng.gen_range(0..destination_candidate.len())];

        let layout = SeparatorLayout {
            separator_id: rng.gen_range(0..context.k),
            to0: t0.clone(),
            to1: t1.clone(),
        };

        let mut new_ans = answer.clone();
        if new_ans.check_and_insert_separator_layout(context, separator, layout.clone(), true) {
            new_ans.check_and_insert_separator_layout(context, separator, layout.clone(), false);
        }
        return new_ans;
    }

    // 1: 既にあるseparatorの接続先を、既にあるseparatorもしくはdisposerにする
    if target == 1 {
        let mut separator_candidate = Vec::new();
        let mut destination_candidate = Vec::new();

        for i in 0..context.m {
            if answer.separator_layout.contains_key(&i) {
                destination_candidate.push(Target {
                    target_kind: TargetKind::Separator,
                    target_id: i,
                });
                separator_candidate.push(i);
            }
        }
        for i in 0..context.n {
            destination_candidate.push(Target {
                target_kind: TargetKind::Disposer,
                target_id: i,
            });
        }

        if separator_candidate.len() == 0 || destination_candidate.len() == 0 {
            return answer.clone();
        }
        let separator = separator_candidate[rng.gen_range(0..separator_candidate.len())];
        let t0 = &destination_candidate[rng.gen_range(0..destination_candidate.len())];
        let t1 = &destination_candidate[rng.gen_range(0..destination_candidate.len())];

        let layout = SeparatorLayout {
            separator_id: rng.gen_range(0..context.k),
            to0: t0.clone(),
            to1: t1.clone(),
        };

        if t0.target_kind == TargetKind::Separator && t0.target_id == separator
            || t1.target_kind == TargetKind::Separator && t1.target_id == separator
        {
            return answer.clone();
        }

        let mut new_ans = answer.clone();
        if new_ans.check_and_insert_separator_layout(context, separator, layout.clone(), true) {
            new_ans.check_and_insert_separator_layout(context, separator, layout.clone(), false);
        }
        return new_ans;
    }

    return answer.clone();
}

Submission Info

Submission Time
Task A - Probabilistic Waste Sorting
User modockey
Language Rust (rustc 1.70.0)
Score 44775446059
Code Size 29420 Byte
Status AC
Exec Time 1952 ms
Memory 2844 KiB

Compile Error

warning: methods `remove_unnecessary_edges` and `separator_has_diposer` are never used
   --> src/main.rs:345:8
    |
178 | impl Answer {
    | ----------- methods in this implementation
...
345 |     fn remove_unnecessary_edges(&mut self, context: &Context) {
    |        ^^^^^^^^^^^^^^^^^^^^^^^^
...
382 |     fn separator_has_diposer(&self, target_id: usize, context: &Context) -> bool {
    |        ^^^^^^^^^^^^^^^^^^^^^
    |
    = note: `#[warn(dead_code)]` on by default

Judge Result

Set Name test_ALL
Score / Max Score 44775446059 / 50000000000
Status
AC × 50
Set Name Test Cases
test_ALL test_0000.txt, test_0001.txt, test_0002.txt, test_0003.txt, test_0004.txt, test_0005.txt, test_0006.txt, test_0007.txt, test_0008.txt, test_0009.txt, test_0010.txt, test_0011.txt, test_0012.txt, test_0013.txt, test_0014.txt, test_0015.txt, test_0016.txt, test_0017.txt, test_0018.txt, test_0019.txt, test_0020.txt, test_0021.txt, test_0022.txt, test_0023.txt, test_0024.txt, test_0025.txt, test_0026.txt, test_0027.txt, test_0028.txt, test_0029.txt, test_0030.txt, test_0031.txt, test_0032.txt, test_0033.txt, test_0034.txt, test_0035.txt, test_0036.txt, test_0037.txt, test_0038.txt, test_0039.txt, test_0040.txt, test_0041.txt, test_0042.txt, test_0043.txt, test_0044.txt, test_0045.txt, test_0046.txt, test_0047.txt, test_0048.txt, test_0049.txt
Case Name Status Exec Time Memory
test_0000.txt AC 1951 ms 2656 KiB
test_0001.txt AC 1951 ms 2692 KiB
test_0002.txt AC 1951 ms 2816 KiB
test_0003.txt AC 1951 ms 2696 KiB
test_0004.txt AC 1951 ms 2844 KiB
test_0005.txt AC 1951 ms 2736 KiB
test_0006.txt AC 1951 ms 2684 KiB
test_0007.txt AC 1951 ms 2808 KiB
test_0008.txt AC 1951 ms 2676 KiB
test_0009.txt AC 1951 ms 2744 KiB
test_0010.txt AC 1951 ms 2760 KiB
test_0011.txt AC 1951 ms 2620 KiB
test_0012.txt AC 1951 ms 2640 KiB
test_0013.txt AC 1951 ms 2676 KiB
test_0014.txt AC 1951 ms 2652 KiB
test_0015.txt AC 1951 ms 2712 KiB
test_0016.txt AC 1951 ms 2804 KiB
test_0017.txt AC 1951 ms 2700 KiB
test_0018.txt AC 1951 ms 2732 KiB
test_0019.txt AC 1952 ms 2796 KiB
test_0020.txt AC 1951 ms 2648 KiB
test_0021.txt AC 1951 ms 2744 KiB
test_0022.txt AC 1951 ms 2760 KiB
test_0023.txt AC 1951 ms 2744 KiB
test_0024.txt AC 1951 ms 2612 KiB
test_0025.txt AC 1951 ms 2812 KiB
test_0026.txt AC 1951 ms 2724 KiB
test_0027.txt AC 1951 ms 2720 KiB
test_0028.txt AC 1951 ms 2668 KiB
test_0029.txt AC 1951 ms 2680 KiB
test_0030.txt AC 1951 ms 2584 KiB
test_0031.txt AC 1951 ms 2700 KiB
test_0032.txt AC 1951 ms 2688 KiB
test_0033.txt AC 1951 ms 2756 KiB
test_0034.txt AC 1951 ms 2728 KiB
test_0035.txt AC 1951 ms 2612 KiB
test_0036.txt AC 1951 ms 2632 KiB
test_0037.txt AC 1951 ms 2680 KiB
test_0038.txt AC 1951 ms 2772 KiB
test_0039.txt AC 1951 ms 2660 KiB
test_0040.txt AC 1951 ms 2672 KiB
test_0041.txt AC 1951 ms 2648 KiB
test_0042.txt AC 1951 ms 2672 KiB
test_0043.txt AC 1951 ms 2692 KiB
test_0044.txt AC 1951 ms 2676 KiB
test_0045.txt AC 1951 ms 2796 KiB
test_0046.txt AC 1951 ms 2704 KiB
test_0047.txt AC 1951 ms 2748 KiB
test_0048.txt AC 1951 ms 2684 KiB
test_0049.txt AC 1951 ms 2756 KiB