Module f

Expand description

ยงABC 358 F - Easiest Maze

refs: https://atcoder.jp/contests/abc358/tasks/abc358_f

use std::cmp::min;

use proconio::input;

// `+++++ ... +++S+`
fn draw_start_line(m: i32) {
    println!("{}S+", "+".repeat(((2 * m) - 1) as usize));
}

// `+++++ ... +++G+`
fn draw_goal_line(m: i32) {
    println!("{}G+", "+".repeat(((2 * m) - 1) as usize));
}

// `+-+-+ ... +-+.+`
fn draw_last_pass_wall(m: i32) {
    println!("{}+.+", "+-".repeat((m - 1) as usize));
}

// `+.+-+ ... +-+-+`
fn draw_first_pass_wall(m: i32) {
    println!("+.{}+", "+-".repeat((m - 1) as usize));
}

// `+o|o|o| ... |o+`
fn draw_vertical_straight(m: i32) {
    println!("+o{}+", "|o".repeat((m - 1) as usize));
}

// `+o.o.o. ... .o+`
fn draw_horizontal_straight(m: i32) {
    println!("+o{}+", ".o".repeat((m - 1) as usize));
}

fn draw_two_lines(m: i32, remain: i32, last_line: bool) -> i32 {
    let consume = min(m - 1, remain / 2);

    let mut path_str = "".to_string();
    let mut wall_str = "".to_string();

    for idx in 0..(2 * m + 1) {
        path_str += if idx == 0 || idx == 2 * m {
            "+"
        } else if idx % 2 == 1 {
            "o"
        } else if (idx / 2) <= consume {
            "."
        } else {
            "|"
        };
    }

    for idx in 0..(2 * m + 1) {
        wall_str += if idx == 0 || idx == 2 * m || idx % 2 == 0 {
            "+"
        } else if (idx / 2) == consume {
            "."
        } else {
            "-"
        };
    }

    println!("{}", path_str.chars().rev().collect::<String>());
    println!("{}", wall_str.chars().rev().collect::<String>());
    println!("{}", path_str.chars().rev().collect::<String>());

    if !last_line {
        draw_last_pass_wall(m);
    }

    remain - consume * 2
}

fn draw_last_three_line(m: i32, remain: i32) {
    let consume = (remain - 2 * (m - 1)) / 2;

    let mut path_str = "+o|".to_string();
    let mut last_path_str = "+o.".to_string();
    let mut wall_str = "+.+".to_string();

    draw_horizontal_straight(m);
    draw_first_pass_wall(m);

    for _ in 0..consume {
        if path_str.len() < ((2 * m + 1) - 4) as usize {
            path_str += "o.o|";
            last_path_str += "o|o.";
            wall_str += ".+.+";
        } else {
            path_str += "o.o+";
            last_path_str += "o|o+";
            wall_str += ".+.+";
        }
    }

    while path_str.len() < (2 * m + 1) as usize {
        if path_str.len() < (2 * m - 1) as usize {
            path_str += "o|";
        } else {
            path_str += "o+";
        }
    }
    while last_path_str.len() < (2 * m + 1) as usize {
        if last_path_str.len() < (2 * m - 1) as usize {
            last_path_str += "o.";
        } else {
            last_path_str += "o+";
        }
    }
    while wall_str.len() < (2 * m + 1) as usize {
        wall_str += "-+";
    }

    println!("{}", path_str);
    println!("{}", wall_str);
    println!("{}", last_path_str);
}

fn draw_even_grid(n: i32, m: i32, k: i32) {
    let mut remain = k - n;

    for idx in 0..(n / 2) {
        remain = draw_two_lines(m, remain, idx == (n / 2 - 1));
    }
}

fn draw_odd_grid(n: i32, m: i32, k: i32) {
    let mut remain = k - n;

    for _ in 0..((n - 3) / 2) {
        remain = draw_two_lines(m, remain, false);
    }
    if remain <= 2 * (m - 1) {
        draw_two_lines(m, remain, false);
        draw_vertical_straight(m);
    } else {
        draw_last_three_line(m, remain);
    }
}

fn main() {
    input! {
      n: i32,
      m: i32,
      k: i32,
    }

    if k < n || (k - n) % 2 != 0 {
        println!("No");
        return;
    }

    println!("Yes");

    draw_start_line(m);
    if n % 2 == 0 {
        draw_even_grid(n, m, k);
    } else {
        draw_odd_grid(n, m, k)
    }
    draw_goal_line(m);
}