算法题思考--1(动态规划,因数)

115 阅读2分钟

算法题思考--1(动态规划,因数)

1.问题背景

本文仅为个人学习记录,有错误请帮我指出,感谢!

题目:一个自然数可以分解成若干个自然数相乘,对于指定自然数n,请求出每种分解自然数之和最小的一个

2.思路

对于一个自然数n,我们发现只要完全分解成一堆质数相乘,就可以使得这些因数的和达到最小。简单证明,

假设a=bc。其中b,c>=2。 ( 此处显然分解成1无意义,会使和更大 ) 则a>=2max{b,c}>=c+b , 由此可见a因数分解后的和比a小。显然a的完全因数分解之后的和最小。

2.1 动态规划思路

定义状态

dp[i] 表示将自然数 i 分解为若干个自然数相乘后,这些自然数的最小和。

初始条件

  • dp[1] = 0,因为 1 无法分解为多个自然数的乘积。
  • 对于质数 pdp[p] = p,因为质数只能分解为自身。

状态转移方程

对于每个 i,我们尝试将其分解为两个数 jk(即 i = j × k),然后更新 dp[i]

dp[i] = min(dp[i], dp[j] + dp[k])

3.代码实现

    import java.util.Arrays;

    public class MinSumFactorization {
        public static int minSumFactorization(int n) {
            // dp[i] 表示将 i 分解为若干个自然数相乘后的最小和
            int[] dp = new int[n + 1];
            Arrays.fill(dp, Integer.MAX_VALUE); // 初始化为最大值
            dp[1] = 0; // 1 无法分解,和为 0

            // 填充 dp 数组
            for (int i = 2; i <= n; i++) {
                // 考虑 i 本身作为一个因子
                dp[i] = Math.min(dp[i], i);

                // 尝试将 i 分解为 j * k
                for (int j = 2; j * j <= i; j++) {
                    if (i % j == 0) {
                        int k = i / j;
                        dp[i] = Math.min(dp[i], dp[j] + dp[k]);
                    }
                }
            }

            return dp[n];
        }

        public static void main(String[] args) {
            int n = 12;
            System.out.println("最小和为: " + minSumFactorization(n)); // 输出 7
        }
    }

4.因数分解

5.参考资料

www.cppblog.com/xpcer/archi…

判断 N 是否是质数,为什么判断到根号 N 就可以了? - 刘明的回答 - 知乎

www.zhihu.com/question/21…