Module d

Module d 

Expand description

ยงABC 424 D - 2x2 Erasing 2

refs: https://atcoder.jp/contests/abc424/tasks/abc424_d

use proconio::{input, marker::Chars};

fn main() {
    input! { t: usize }

    for _ in 0..t {
        solve();
    }
}
const INF: usize = 1e+9 as usize;

fn solve() {
    input! {
        h: usize, w: usize,
        field: [Chars; h],
    }

    let bit_field = to_bits(field);

    let pat_max = 2usize.pow(w as u32);
    let mut dp = vec![vec![INF; pat_max]; h];

    for pat in 0..pat_max {
        if can_make(bit_field[0], pat) {
            dp[0][pat] = changed_bit(bit_field[0], pat);
        }
    }

    for row in 1..h {
        for pat in 0..pat_max {
            if can_make(bit_field[row], pat) {
                dp[row][pat] = (0..pat_max)
                    .filter(|&prev_pat| dp[row - 1][prev_pat] != INF)
                    .filter(|&prev_pat| !has_black_region(prev_pat, pat, w))
                    .map(|prev_pat| dp[row - 1][prev_pat] + changed_bit(bit_field[row], pat))
                    .min()
                    .unwrap_or(INF);
            }
        }
    }

    println!("{}", dp[h - 1].iter().min().expect("Not empty"));
}

fn can_make(source: usize, dist: usize) -> bool {
    !source & dist == 0
}

fn changed_bit(source: usize, dist: usize) -> usize {
    (source & !dist).count_ones() as usize
}

fn has_black_region(prev_pat: usize, current_pat: usize, w: usize) -> bool {
    let mut mask = 1 + (1 << 1);

    while mask < (1 << w) {
        if prev_pat & mask == mask && current_pat & mask == mask {
            return true;
        }
        mask <<= 1;
    }

    false
}

fn to_bits(field: Vec<Vec<char>>) -> Vec<usize> {
    field.into_iter().map(to_bit).collect()
}

fn to_bit(row: Vec<char>) -> usize {
    row.into_iter().enumerate().fold(
        0usize,
        |acc, (idx, c)| if c == '#' { acc + (1 << idx) } else { acc },
    )
}