2023.6.8 铺瓷砖

这个问题是一个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
}
}

浙公网安备 33010602011771号