Leetcode 1240:铺瓷砖(超详细的解法!!!)

2023-10-16 19:59

本文主要是介绍Leetcode 1240:铺瓷砖(超详细的解法!!!),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

你是一位施工队的工长,根据设计师的要求准备为一套设计风格独特的房子进行室内装修。

房子的客厅大小为 n x m,为保持极简的风格,需要使用尽可能少的 正方形 瓷砖来铺盖地面。

假设正方形瓷砖的规格不限,边长都是整数。

请你帮设计师计算一下,最少需要用到多少块方形瓷砖?

示例 1:

输入:n = 2, m = 3
输出:3
解释:3 块地砖就可以铺满卧室。2 块 1x1 地砖1 块 2x2 地砖

示例 2:

输入:n = 5, m = 8
输出:5

示例 3:

输入:n = 11, m = 13
输出:6

提示:

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

解题思路

这是一个经典的问题,该问题源自这篇论文Tiling a rectangle with the fewest squares。当然我们这里肯定不会这么复杂的去做,这里给出两种解法。

首先考虑dfs的解法,也就是一行一行的去枚举可以放的矩形,例如:

此时我们将第一行的所有矩形都确定了,接着考虑第二行的矩形,那么这里应该是从绿色(第2个)下面开始放,然后再放紫色的(第4个),也就是从最低高度开始放。当所有矩形的高度都是大矩形的高度n时,那么此时摆放成功,记录结果。为了记录每个矩形的高度,我们需要开辟m大小的数组(记录每个位置的高度)。对于第一个例子,最后记录(最后一层)的就是[1,2,2]。需要注意的是,我们实际放正方形的时候采用贪心策略(从最大的开始放),所以并不会出现上图中的情形。

最后代码非常简洁:

class Solution:def tilingRectangle(self, n: int, m: int) -> int:res = m * n    def dfs(ht, moves):if all(h == n for h in ht):res = min(res, moves)returnif moves >= res:returnidx = ht.index(min(ht))for i in range(min(m - idx, n - ht[idx]), 0, -1):# 正方形大小nht = ht[:]for j in range(i): # 正方形放入nht[idx + j] += idfs(nht, moves + 1) dfs([0] * m, 0)return res

这个问题还可以换一种方式思考,仔细观察题目给的例子,实际上描述了三种切分方式:横切、竖切和包含中心正方形的切分(第三个图)。

对于横切来说,最后的结果就应该来自上面一个矩形和下面一个矩形;对于竖切来说,最后的结果就应该来自左边一个矩形和右边一个矩形;对于包含正方形的形式来说,可以看成下面这种方式:

将左上角两个正方形何在一起看,我们需要确定中心矩形的大小l和位置(i,j),那么左上角矩形的大小就是(i+l,j),右上角矩形的大小就是(x-(i+l),j+l),左下角矩形的大小就是(i,y-j),右下角矩形的大小就是(x-i,y-(j+l)),其中xy表示外部整个矩形的宽度和高度。

接着思考边界问题,当x==y的时候,只要一个正方形就可以了。而当x==1的时候,需要y个正方形。当y==1的时候,需要x个正方形。

from functools import lru_cache
class Solution:def tilingRectangle(self, n: int, m: int) -> int:@lru_cache(None)def dfs(x, y):if x == y:return 1if x == 1:return yif y == 1:return xres = x * yfor i in range(1, x//2 + 1):# 竖切res = min(res, dfs(i, y) + dfs(x - i, y))for j in range(1, y//2 + 1):# 横切res = min(res, dfs(x, j) + dfs(x, y - j))for l in range(1, min(x, y)):# 包含中心for i in range(1, x-l):for j in range(1, y-l):res = min(res, dfs(i+l, j) + dfs(x-(i+l), j+l) + dfs(i, y-j) + dfs(x-i, y-(j+l)) + 1)return resreturn dfs(n, m)

上面这个代码还可以继续优化,我们可以去掉包含中心的情况。因为题目给的数据最大是13,而包含中心矩形的最优解只会出现在(11,13)(13,11)这两种情况的时候,此时的最优解是6,可以查看这个表。

from functools import lru_cache
class Solution:def tilingRectangle(self, n: int, m: int) -> int:@lru_cache(None)def dfs(x, y):if (x, y) in {(11, 13), (13, 11)}:return 6if x == y:return 1res = x * yfor i in range(1, x//2 + 1):res = min(res, dfs(i, y) + dfs(x - i, y))for j in range(1, y//2 + 1):res = min(res, dfs(x, j) + dfs(x, y - j))return resreturn dfs(n, m)

reference:

https://www.bilibili.com/video/av73704545?from=search&seid=6528127797779899524

我将该问题的其他语言版本添加到了我的GitHub Leetcode

如有问题,希望大家指出!!!

这篇关于Leetcode 1240:铺瓷砖(超详细的解法!!!)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!


原文地址:https://blog.csdn.net/qq_17550379/article/details/102787329
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.chinasem.cn/article/220467

相关文章

spring security 超详细使用教程及如何接入springboot、前后端分离

《springsecurity超详细使用教程及如何接入springboot、前后端分离》SpringSecurity是一个强大且可扩展的框架,用于保护Java应用程序,尤其是基于Spring的应用... 目录1、准备工作1.1 引入依赖1.2 用户认证的配置1.3 基本的配置1.4 常用配置2、加密1. 密

WinForms中主要控件的详细使用教程

《WinForms中主要控件的详细使用教程》WinForms(WindowsForms)是Microsoft提供的用于构建Windows桌面应用程序的框架,它提供了丰富的控件集合,可以满足各种UI设计... 目录一、基础控件1. Button (按钮)2. Label (标签)3. TextBox (文本框

Spring Boot 集成 Solr 的详细示例

《SpringBoot集成Solr的详细示例》:本文主要介绍SpringBoot集成Solr的详细示例,本文通过实例代码给大家介绍的非常详细,感兴趣的朋友一起看看吧... 目录环境准备添加依赖配置 Solr 连接定义实体类编写 Repository 接口创建 Service 与 Controller示例运行

自研四振子全向增益天线! 中兴问天BE6800Pro+路由器拆机和详细评测

《自研四振子全向增益天线!中兴问天BE6800Pro+路由器拆机和详细评测》中兴问天BE6800Pro+路由器已经上市,新品配备自研四振子全向增益天线,售价399元,国补到手339.15元,下面我们... 中兴问天BE6800Pro+路由器自上市以来,凭借其“旗舰性能,中端价格”的定位,以及搭载三颗自研芯片

ubuntu20.0.4系统中安装Anaconda的超详细图文教程

《ubuntu20.0.4系统中安装Anaconda的超详细图文教程》:本文主要介绍了在Ubuntu系统中如何下载和安装Anaconda,提供了两种方法,详细内容请阅读本文,希望能对你有所帮助... 本文介绍了在Ubuntu系统中如何下载和安装Anaconda。提供了两种方法,包括通过网页手动下载和使用wg

SpringBoot实现二维码生成的详细步骤与完整代码

《SpringBoot实现二维码生成的详细步骤与完整代码》如今,二维码的应用场景非常广泛,从支付到信息分享,二维码都扮演着重要角色,SpringBoot是一个非常流行的Java基于Spring框架的微... 目录一、环境搭建二、创建 Spring Boot 项目三、引入二维码生成依赖四、编写二维码生成代码五

Java中 instanceof 的用法详细介绍

《Java中instanceof的用法详细介绍》在Java中,instanceof是一个二元运算符(类型比较操作符),用于检查一个对象是否是某个特定类、接口的实例,或者是否是其子类的实例,这篇文章... 目录引言基本语法基本作用1. 检查对象是否是指定类的实例2. 检查对象是否是子类的实例3. 检查对象是否

将图片导入Python的turtle库的详细过程

《将图片导入Python的turtle库的详细过程》在Python编程的世界里,turtle库以其简单易用、图形化交互的特点,深受初学者喜爱,随着项目的复杂度增加,仅仅依靠线条和颜色来绘制图形可能已经... 目录开篇引言正文剖析1. 理解基础:Turtle库的工作原理2. 图片格式与支持3. 实现步骤详解第

Docker安装MySQL镜像的详细步骤(适合新手小白)

《Docker安装MySQL镜像的详细步骤(适合新手小白)》本文详细介绍了如何在Ubuntu环境下使用Docker安装MySQL5.7版本,包括从官网拉取镜像、配置MySQL容器、设置权限及内网部署,... 目录前言安装1.访问docker镜像仓库官网2.找到对应的版本,复制右侧的命令即可3.查看镜像4.启

Java版本不兼容问题详细解决方案步骤

《Java版本不兼容问题详细解决方案步骤》:本文主要介绍Java版本不兼容问题解决的相关资料,详细分析了问题原因,并提供了解决方案,包括统一JDK版本、修改项目配置和清理旧版本残留等步骤,需要的朋... 目录错误原因分析解决方案步骤第一步:统一 JDK 版本第二步:修改项目配置第三步:清理旧版本残留兼容性对