Skip to content

Commit 635de65

Browse files
author
aaron.liu
committed
update
1 parent cb7b171 commit 635de65

File tree

2 files changed

+130
-0
lines changed

2 files changed

+130
-0
lines changed

Linkedin/tallest tower.py

Lines changed: 130 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,130 @@
1+
'''
2+
suppose you are trying to build a very tall tower. you have a collection of blocks to make your tower out of.
3+
For each block type, you are given the numbers of blocks you have of that type, its weight, and the max. weight
4+
that block can support above it and including itself. suppose for now that all blocks have the same height(1 meter).
5+
what's the tallest tower you can construct by stacking these blocks?
6+
7+
Example input, with each row representing a block type of format: number of blocks, weight, max support weight:
8+
[ [1, 1, 1], [100, 3, 100], [10, 2, 10]]
9+
Example output: 35
10+
for this sample problem, the best solution is to stack the single (1,1) block on top, then 4 of (2,10) blocks under it,
11+
giving a total weight of 9; we can then stack 30 more (3, 100) blocks at the base.
12+
13+
14+
思路: dp
15+
dp[i][j]表示使用前i种砖块 总重量为j时的最大高度
16+
dp[i][j]可以由两种方式转移得来
17+
1. dp[i-1][j]:不使用第i块砖
18+
2. dp[i-1][j-k*weight[i]] for k:1,2,...count (当前砖可以用1,2,...count块)
19+
两者取一个max 就是dp[i][j]
20+
'''
21+
from typing import List
22+
23+
def max_tower_height(blocks: List[List[int]]) -> int:
24+
# 按承重能力(max_support)从小到大排序
25+
blocks.sort(key=lambda x: x[2])
26+
27+
n = len(blocks)
28+
# 所有blocks加在一起的总重量之和 是理论上dp[i][j]的j那一维的最大值
29+
max_weight = sum(block[0] * block[1] for block in blocks)
30+
31+
# 初始化dp数组,dp[i][j]表示使用前i种砖块,总重量为j时的最大高度
32+
dp = [[0] * (max_weight + 1) for _ in range(n + 1)]
33+
34+
for i in range(1, n + 1):
35+
count, weight, max_support = blocks[i-1]
36+
for j in range(max_weight + 1):
37+
# 不使用当前砖块
38+
dp[i][j] = dp[i - 1][j]
39+
40+
# 尝试使用当前砖块
41+
for k in range(1, count + 1):
42+
if j >= k * weight and j <= max_support:
43+
dp[i][j] = max(dp[i][j], dp[i - 1][j - k * weight] + k)
44+
45+
# 返回所有可能总重量中的最大高度
46+
return max(dp[n])
47+
48+
# 测试用例
49+
blocks1 = [[1, 1, 1], [100, 3, 100], [10, 2, 10]]
50+
result1 = max_tower_height(blocks1)
51+
print(f"最大高度: {result1}")
52+
53+
blocks2 = [[4, 1, 10], [1, 9, 9], [4, 2, 18]]
54+
result2 = max_tower_height(blocks2)
55+
print(f"最大高度: {result2}")
56+
57+
58+
# followup: 如果每块砖的高度不一样
59+
# 还是按照承重能力从小到大排序
60+
def max_tower_height_w(blocks):
61+
# 按承重能力从小到大排序
62+
blocks.sort(key=lambda x: x[2])
63+
64+
n = len(blocks)
65+
max_weight = max(block[2] for block in blocks)
66+
67+
# 初始化dp数组
68+
dp = [[0] * (max_weight + 1) for _ in range(n + 1)]
69+
70+
for i in range(1, n + 1):
71+
count, weight, support, height = blocks[i - 1]
72+
for w in range(max_weight + 1):
73+
dp[i][w] = dp[i-1][w] # 不使用当前块
74+
75+
# 尝试使用当前砖块 枚举可能用多少块当前砖
76+
for k in range(1, count + 1):
77+
if k * weight <= w and w <= support:
78+
dp[i][w] = max(dp[i][w], dp[i-1][w - k * weight] + k * height)
79+
80+
return dp[n][max_weight]
81+
82+
# 测试样例
83+
blocks = [[1, 1, 1, 2], [100, 3, 100, 1], [10, 2, 10, 3]] # 答案是45 用5个blocks[2] 用30个blocks[1] 不用blocks[0]
84+
result = max_tower_height_w(blocks)
85+
print(f"能建造的最高塔楼高度为: {result}")
86+
87+
'''
88+
def dfs(weight:int, index:int, blocks:List[List[int]], dp:List[List[int]]) -> int:
89+
# 基本情况:当没有更多砖块可用时
90+
if index == len(blocks):
91+
return 0
92+
93+
# 如果已经计算过这种情况,直接返回结果
94+
if dp[weight][index] != -1:
95+
return dp[weight][index]
96+
97+
# 不使用当前砖块
98+
result = dfs(weight, index + 1, blocks, dp)
99+
100+
count, block_weight, max_support = blocks[index]
101+
102+
# 尝试使用当前砖块
103+
if weight + block_weight <= max_support:
104+
for i in range(1, count + 1):
105+
if weight + i * block_weight > max_support:
106+
break
107+
result = max(result, i + dfs(weight + i * block_weight, index + 1, blocks, dp))
108+
109+
# 存储结果
110+
dp[weight][index] = result
111+
return result
112+
113+
def max_tower_height(blocks: List[List[int]]) -> int:
114+
# 按重量升序排序
115+
blocks.sort(key=lambda x: x[2])
116+
117+
n = len(blocks)
118+
max_weight = sum(block[0] * block[1] for block in blocks)
119+
120+
# 初始化dp数组
121+
dp = [[-1] * n for _ in range(max_weight + 1)]
122+
123+
return dfs(0, 0, blocks, dp)
124+
125+
# 测试用例
126+
blocks = [[1, 1, 1], [100, 3, 100], [10, 2, 10]]
127+
result = max_tower_height(blocks)
128+
print(f"max height: {result}")
129+
130+
'''

Meta/test.py

Whitespace-only changes.

0 commit comments

Comments
 (0)