Loading

2023.6.8 铺瓷砖

image

这个问题是一个NP-完全问题,所以基本上只能用爆搜的方法去做,从数据范围是13x13也可以看出来,在暗示用爆搜去做。

从大到小枚举正方形的长度k,尝试把这个正方形的左上角放到\((x, y)\)处。
如果\((x,y)\)已经被其他正方形覆盖了,就尝试\((x,y+1)\)。否则,放置成功,调到\((x,y+k)\)处继续尝试放置。

use std::cmp::min;

impl Solution 
{

    pub fn tiling_rectangle(n: i32, m: i32) -> i32 
    {
        let (n, m, mut res) = (n as usize, m as usize, 0x3f3f3f3f);
        let mut g = vec![vec![false; m]; n];
        
        Self::dfs(&mut g, 0, 0, n, m, 0, &mut res);
        res
    }

    pub fn dfs(g: &mut Vec<Vec<bool>>, x: usize, y: usize, n: usize, m: usize, cnt: i32, res: &mut i32)
    {
        if cnt >= *res { return; }
        if x >= n { *res = cnt; return; }
        if y >= m { Self::dfs(g, x + 1, 0, n, m, cnt, res); return; }
        if g[x][y] { Self::dfs(g, x, y + 1, n, m, cnt, res); return; }
        
        let mut k = min(n - x, m - y);
        while k >= 1 && Self::check(g, x, y, n, m, k)
        {
            Self::fillUp(g, x, y, n, m, k, true);
            Self::dfs(g, x, y + k, n, m, cnt + 1, res);
            Self::fillUp(g, x, y, n, m, k, false);
            k -= 1;
        }
    }

    pub fn fillUp(g: &mut Vec<Vec<bool>>, x: usize, y: usize, n: usize, m: usize, k: usize, val: bool)
    {
        for i in 0..k {
            for j in 0..k {
                g[x + i][y + j] = val;
            }
        }
    }

    pub fn check(g: &Vec<Vec<bool>>, x: usize, y: usize, n: usize, m: usize, k: usize) -> bool
    {
        for i in 0..k {
            for j in 0..k {
                if g[x + i][y + j] == true {
                    return false;
                }
            }
        }
        true
    }
}
posted @ 2023-06-08 12:52  烤肉kr  阅读(16)  评论(0)    收藏  举报