LeetCode 1240. Tiling a Rectangle with the Fewest Squares 瓷砖

231 篇文章 0 订阅

Given a rectangle of size n x m, find the minimum number of integer-sided squares that tile the rectangle.

 

Example 1:

Input: n = 2, m = 3
Output: 3

Example 2:

Input: n = 5, m = 8
Output: 5

Example 3:

Input: n = 11, m = 13
Output: 6

 

Constraints:

  • 1 <= n <= 13
  • 1 <= m <= 13

据说这是一篇有paper的题目,paper解法比较复杂,不适合LeetCode写,首先感谢https://blog.csdn.net/qq_17550379/article/details/102787329提供快速的写法。

思路一: 铺地砖的问题可以压缩成一个int表示某行铺的情况https://blog.csdn.net/taoqick/article/details/22720783),也可以记录一下某列最多铺了多少行,然后依次考虑每行铺满了没有。。。这是一种比较通用的思路。在这题里,要铺的正方形从大到小变化,要知道上届不光是两个边界,还有可能右边铺了更高的,所以用get_largest先求一下上届,然后贪心地去尝试。。

class Solution:
    def tilingRectangle(self, n, m):
        res = m*n

        def get_largest(ht,n,m,idx):
            upper = min(m-idx, n-ht[idx])
            ret = 1
            while (ret < upper and ht[idx] == ht[idx+ret]):
                ret += 1
            return ret

        def dfs(ht, moves):
            nonlocal res
            if all(h == n for h in ht):
                res = min(res, moves)
                return
            if moves >= res:
                return
            idx = ht.index(min(ht))
            largest = get_largest(ht,n,m,idx)
            for i in range(largest, 0, -1):# 正方形大小
                nht = ht[:]
                print(ht[idx:idx+i])
                for j in range(i): # 正方形放入
                    nht[idx + j] += i
                dfs(nht, moves + 1)

        dfs([0] * m, 0)
        return res

思路二:思路二比较trick,搞成横切,竖切,包围三种状态,至于为什么只有这三种,感觉是从例子里观察出来的,数据范围更大确实有可能有更多情况,个人并不喜欢这个解法

from functools import lru_cache


class Solution:
    def tilingRectangle(self, n, m):
        @lru_cache(None)
        def dfs(x, y):
            if (x == 1):
                return y
            elif (y == 1):
                return x
            elif (x == y):
                return 1

            res = n*m
            for i in range(1, ((x >> 1) + 1)):
                res = min(res, dfs(x - i, y) + dfs(i, y))
            for i in range(1, ((y >> 1) + 1)):
                res = min(res, dfs(x, y - i) + dfs(x, i))

            for edge in range(1, min(x, y) - 1):
                for i in range(1, x - edge):
                    for j in range(1, y - edge):
                        res = min(res, 1 + dfs(i, edge + j) +
                                           dfs(i + edge, y - edge - j) + #bug1: i+x
                                           dfs(x - i - edge, y - j) +
                                           dfs(x - i, j))
            return res
        return dfs(n,m)

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值