刷题笔记 最小周长巧克力板组合 题解 | 豆包MarsCode AI刷题

3 阅读3分钟

问题描述

小U准备了一些边长为整数的正方形巧克力板,希望选出若干块巧克力板,使它们的总面积恰好等于给定的整数n。巧克力板的周长应尽可能小。巧克力板的总面积恰好为n,而总周长为这些正方形边长的四倍和。请你帮助小U找到一个最优方案,输出最短的周长总和。

问题理解

经过简单分析我们需要找到若干个边长为整数的正方形巧克力板,使它们的总面积恰好等于给定的整数 n,并且总周长最小。周长最小即意味着尽量使用边长较大的正方形。

数据结构选择

在这道题目中由于我们只需要计算周长,不需要存储具体的正方形边长,因此不需要复杂的数据结构。我们只需要一个变量来累加周长即可。

解题所用到的算法步骤

算法步骤

  1. 初始化周长总和

    • 使用一个变量 perimeter 来记录总周长,初始值为 0。
  2. 贪心选择正方形

    • 使用贪心算法,每次选择最大的正方形边长 k,使得 k^2 <= n
    • 计算当前正方形的周长并累加到 perimeter 中。
    • 更新 n 为 n - k^2,表示剩余需要覆盖的面积。
  3. 重复步骤

    • 重复上述步骤,直到 n 变为 0。

详细步骤

  1. 找到最大的正方形边长

    • 计算 k = int(n ** 0.5),即 k 是小于等于 sqrt(n) 的最大整数。
  2. 更新周长和剩余面积

    • 计算当前正方形的周长 4 * k 并累加到 perimeter 中。
    • 更新 n 为 n - k^2
  3. 循环直到 n 为 0

    • 重复上述步骤,直到 n 变为 0。

前置步骤完成代码详解

  1. 函数定义

    def solution(n: int) -> int:

定义了一个名为 solution 的函数,接受一个整数 n 作为参数,并返回一个整数。

  1. 初始化周长总和

    perimeter = 0

初始化一个变量 perimeter,用于记录总周长,初始值为 0。

  1. 循环寻找正方形

    while n > 0:

使用 while 循环,当 n 大于 0 时,继续寻找正方形。

  1. 找到最大的正方形边长

    k = int(n ** 0.5)

计算 k = int(n ** 0.5),即 k 是小于等于 sqrt(n) 的最大整数。这个 k 就是当前最大的正方形边长。

  1. 更新剩余面积

    n -= k * k

更新 n 为 n - k^2,表示剩余需要覆盖的面积。

  1. 累加周长

    perimeter += 4 * k

计算当前正方形的周长 4 * k 并累加到 perimeter 中。

  1. 返回结果

    return perimeter

当 n 变为 0 时,循环结束,返回总周长 perimeter

总结

这道题通过寻找若干个正方形巧克力板,使它们的总面积恰好等于给定的整数 n,并且总周长最小,展示了贪心算法的核心思想。通过每次选择最大的正方形边长,可以逐步减少剩余面积,从而确保总周长最小。这个过程不仅帮助我理解了贪心算法的应用场景,还让我掌握了如何通过简单的数学运算(如平方根)来优化问题的解决方案。此外,通过实现和调试代码,我学会了如何在循环中动态更新变量,并逐步逼近问题的最优解。这道题不仅提升了我的编程技能,还加深了对算法设计和优化的理解,为解决类似的最优化问题提供了宝贵的经验。

完整代码

def solution(n: int) -> int:
    # 初始化周长总和
    perimeter = 0
    
    # 当 n 大于 0 时,继续寻找正方形
    while n > 0:
        # 找到最大的正方形边长 k,使得 k^2 <= n
        k = int(n ** 0.5)
        
        # 更新 n 为 n - k^2
        n -= k * k
        
        # 累加周长
        perimeter += 4 * k
    
    return perimeter

if __name__ == '__main__':
    print(solution(n=11) == 20)
    print(solution(n=13) == 20)
    print(solution(n=25) == 20)