C/C++ 数据结构五大核心算法之动态规划算法-给你一根长度为 n 的金条,请把金条剪成 m 段 (m 和 n 都是整数,n>1 并且 m>1)每断金条的长度记为 k[0],k[1],…,k[m].请问 k[0] k[1]…*k[m]可能的最大乘积是多少?

发布时间 2023-08-03 11:20:14作者: wshidaboss
动态规划也是一种分治思想,但与分治算法不同的是,分治算法是把原问题分解为若干子问题,自顶向下,求解各子问题,合并子问题的解从而得到原问题的解。动态规划也是自顶向下把原问题分解为若干子问题,不同的是,然后自底向上,先求解最小的子问题,把结果存储在表格中,在求解大的子问题时,直接从表格中查询小的子问题的解,避免重复计算,从而提高算法效率。
什么时候要用动态规划?
如果要求一个问题的最优解(通常是最大值或者最小值),而且该问题能够分解成若干个子问题,
并且小问题之间也存在重叠的子问题,则考虑采用动态规划。
怎么使用动态规划?
1. 判题题意是否为找出一个问题的最优解
2. 从上往下分析问题,大问题可以分解为子问题,子问题中还有更小的子问题
3. 从下往上分析问题 ,找出这些问题之间的关联(状态转移方程)
4. 讨论底层的边界问题
5. 解决问题(通常使用数组进行迭代求出最优解)
例题:给你一根长度为 n 的金条,请把金条剪成 m 段 (m 和 n 都是整数,n>1 并且 m>1)每断金条的长度记为 k[0],k[1],…,k[m].请问 k[0] k[1]…*k[m]可能的最大乘积是多少?
思路:1.首先,根据题意我们可以知道金条的长度和段数都要大于1,也就是说段数要从2开始;2.又因为金条的长度和段数都是整数,所以段数的范围是2~n,比如一根10cm的金条,最多能分成10段,每段1cm;3.接下来我们找找关联的子问题,当金条的长度小于2时,无法继续划分,最大的乘积返回0;当金条的长度为2时,可分为2段,每段的长度为1,最大的乘积即为1;当金条的长度为3时,可分为2段,一段长度为1,一段长度为2,最大的乘积即为2;4.最后我们来找找当金条长度大于3时的最大的乘积有何规律。
#include <iostream>
#include <Windows.h>
using namespace std;
long long getMaxMul(int n) {
    if (n < 2) return 0;
    if (n == 2) return 1;
    if (n == 3) return 2;
    long long * k = new long long[n+1];
    k[0] = 0;
    k[1] = 1;
    k[2] = 2;
    k[3] = 3;
    for (int i = 4; i <= n; i++) {
        long long max = 0;
        for (int j = 1; j <= i / 2; j++) {
            long long ret = k[j] * k[i-j];
            if (max < ret) {
                max = ret;
            }
        }
        k[i]=max;
    }
    return k[n];
    delete[] k;
}
int main() {
    int n = 0;//n为金条长度
    cout << "请输入金条的长度:";
    cin >> n;
    cout << "可能的最大乘积是:" << getMaxMul(n) << endl;
    
    system("pause");
    return 0;
}