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

51 阅读2分钟

1. 理解问题

  • 我们需要将 n 分解成若干个正方形的面积和。
  • 每个正方形的面积是边长的平方。
  • 目标是使得这些正方形的总周长最小。

2. 数据结构的选择

  • 我们可以使用动态规划(Dynamic Programming, DP)来解决这个问题。
  • 定义一个数组 dp,其中 dp[i] 表示将整数 i 分解成若干个正方形面积和时的最小周长。

3. 算法步骤

  1. 初始化

    • dp[0] = 0,因为面积为0时不需要任何正方形。
    • 对于其他 i,初始化 dp[i] 为一个较大的值(例如 i * 4,因为最坏情况下每个正方形的边长为1)。
  2. 状态转移

    • 对于每个 i,尝试将其分解成一个较大的正方形和剩余的部分。
    • 设当前正方形的边长为 k,则 k 的范围是从 1 到 sqrt(i)
    • 对于每个 k,计算 dp[i] = min(dp[i], dp[i - k^2] + 4 * k),其中 4 * k 是当前正方形的周长。
  3. 结果

    • 最终 dp[n] 就是将 n 分解成若干个正方形面积和时的最小周长。

4. 优化

  • 由于我们只需要计算 dp[n],可以在计算过程中只保留必要的 dp 值,减少空间复杂度。
public class Main {
    public static int solution(int n) {
        // dp[i] 表示将整数 i 分解成若干个正方形面积和时的最小周长
        int[] dp = new int[n + 1];
        
        // 初始化 dp 数组
        for (int i = 1; i <= n; i++) {
            dp[i] = i * 4; // 最坏情况下每个正方形的边长为1
        }
        
        // 动态规划求解
        for (int i = 1; i <= n; i++) {
            for (int k = 1; k * k <= i; k++) {
                dp[i] = Math.min(dp[i], dp[i - k * k] + 4 * k);
            }
        }
        
        return dp[n];
    }

    public static void main(String[] args) {
        System.out.println(solution(11) == 20);
        System.out.println(solution(13) == 20);
        System.out.println(solution(25) == 20);
    }
}

代码解释

  1. 初始化

    • dp[i] 初始化为 i * 4,表示最坏情况下每个正方形的边长为1。
  2. 动态规划

    • 对于每个 i,尝试将其分解成一个较大的正方形和剩余的部分。
    • 设当前正方形的边长为 k,则 k 的范围是从 1 到 sqrt(i)
    • 对于每个 k,计算 dp[i] = min(dp[i], dp[i - k^2] + 4 * k),其中 4 * k 是当前正方形的周长。
  3. 结果

    • 最终 dp[n] 就是将 n 分解成若干个正方形面积和时的最小周长。

测试

  • 在 main 方法中,我们测试了 n = 11n = 13, 和 n = 25 的情况,并验证了结果是否正确。