pygorithm/greedy/max_question.py

77 lines
3.0 KiB
Python
Raw Normal View History

2023-12-22 19:23:39 +08:00
"""
输入一个数组 ht其中的每个元素代表一个垂直隔板的高度数组中的任意两个隔板以及它们之间的空间可以组成一个容器
容器的容量等于高度和宽度的乘积面积其中高度由较短的隔板决定宽度是两个隔板的数组索引之差
请在数组中选择两个隔板使得组成的容器的容量最大返回最大容量
容器由任意两个隔板围成因此本题的状态为两个隔板的索引记为 [i,j]
根据题意容量等于高度乘以宽度其中高度由短板决定宽度是两隔板的数组索引之差设容量为 cap[i,j]则可得计算公式
cap[i,j] = min(ht[i],ht[j]) * (j - i)
贪心策略确定:
- 现选取一个状态 [i, j]其满足索引 i<j 且高度 ht[i]<ht[j]
- 若此时将长板 j 向短板 i 靠近则容量一定变小因为i仍然是短板
- 向内移动ii的高度增大后容量才可能变大
- 由此便可推出本题的贪心策略初始化两指针分列容器两端每轮向内收缩短板对应的指针直至两指针相遇
"""
import math
def max_capacity(ht: list[int]) -> int:
i, j = 0, len(ht) - 1
res = 0
while i < j:
cap = min(ht[i], ht[j]) * (j - i)
res = max(res, cap)
if ht[i] < ht[j]:
i += 1
else:
j -= 1
return res
"""
最大切分乘积问题
给定一个正整数 n将其切分为至少两个正整数的和求切分后所有整数的乘积最大是多少?
假设我们将 n 切分为 m 个整数因子其中第 i 个因子记为 ni
贪心策略确定
根据经验两个整数的乘积往往比它们的加和更大假设从 n 中分出一个因子 2
则它们的乘积为 2(n-2)我们将该乘积与 n 作比较
2*(n-2)>=n --> n>=4
也就是当 n>=4 切分出一个 2 后乘积会变大这说明大于等于 4 的整数都应该被切分
贪心策略一如果切分方案中包含 >=4 的因子那么它就应该被继续切分最终的切分方案只应出现 123这三个因子
123 这三个因子中显然 1 是最差的因为 1*(n-1)<n恒成立
贪心策略二在切分方案中最多只应存在两个 2因为三个 2总是可以替换为两个 3从而获得更大的乘积
代码实现
我们无须通过循环来切分整数而可以利用向下整除运算得到 3 的个数 a用取模运算得到余数 b
此时有
n = 3a + b
请注意对于 n<=3 的边界情况必须拆分出一个 1乘积为 1(n-1)
"""
def max_product_cutting(n: int) -> int:
if n <= 3:
return 1 * (n - 1)
a, b = n // 3, n % 3
if b == 1:
# 当余数为 1 时,将一对 1 * 3 转为 2 * 2
return int(math.pow(3, a - 1)) * 2 * 2
if b == 2:
# 当余数为 2 时不用处理
return int(math.pow(3, a)) * 2
# 余数为 0 时不用处理
return int(math.pow(3, a))