Leecode刷题C语言之切棍子的最小成本

执行结果:通过

执行用时和内存消耗如下:

Leecode刷题C语言之切棍子的最小成本_第1张图片

题目:切棍子的最小成本

有一根长度为 n 个单位的木棍,棍上从 0 到 n 标记了若干位置。例如,长度为 6 的棍子可以标记如下:

Leecode刷题C语言之切棍子的最小成本_第2张图片

给你一个整数数组 cuts ,其中 cuts[i] 表示你需要将棍子切开的位置。

你可以按顺序完成切割,也可以根据需要更改切割的顺序。

每次切割的成本都是当前要切割的棍子的长度,切棍子的总成本是历次切割成本的总和。对棍子进行切割将会把一根木棍分成两根较小的木棍(这两根木棍的长度和就是切割前木棍的长度)。请参阅第一个示例以获得更直观的解释。

返回切棍子的 最小总成本 。

示例 1:

Leecode刷题C语言之切棍子的最小成本_第3张图片

输入:n = 7, cuts = [1,3,4,5]
输出:16
解释:按 [1, 3, 4, 5] 的顺序切割的情况如下所示:

Leecode刷题C语言之切棍子的最小成本_第4张图片

第一次切割长度为 7 的棍子,成本为 7 。第二次切割长度为 6 的棍子(即第一次切割得到的第二根棍子),第三次切割为长度 4 的棍子,最后切割长度为 3 的棍子。总成本为 7 + 6 + 4 + 3 = 20 。
而将切割顺序重新排列为 [3, 5, 1, 4] 后,总成本 = 16(如示例图中 7 + 4 + 3 + 2 = 16)。

解题思路:

  1. 排序切割点
    • 使用 qsort 函数对 cuts 数组进行排序。排序函数 comp 比较两个整数指针指向的值,并返回它们的差值,用于确保 cuts 数组按升序排列。
  2. 扩展切割点数组
    • 创建一个新的数组 tmp,其长度为 cutsSize + 2。这是因为我们需要考虑木棍的两端(即位置 0 和 n),作为切割的起始和结束点。
    • 将 cuts 数组中的值复制到 tmp 数组的 1 到 cutsSize 位置,并在 tmp[0] 和 tmp[cutsSize + 1] 分别设置 0 和 n,表示木棍的起始和结束位置。
  3. 动态规划初始化
    • 创建一个二维数组 f,大小为 (cutsSize + 2) x (cutsSize + 2)f[i][j] 表示从 tmp[i-1] 到 tmp[j] 之间的木棍切割的最小成本。
    • 使用 memset 函数将 f 数组的所有元素初始化为 0
  4. 动态规划求解
    • 采用动态规划的思想,从右往左(即从较大的切割段到较小的切割段)填充 f 数组。
    • 对于每个可能的切割段 [i, j],遍历所有可能的切割点 ki <= k <= j),计算将 [i, j] 分为 [i, k-1] 和 [k+1, j] 两部分时的成本,并加上当前段的总长度 tmp[j + 1] - tmp[i - 1]
    • 更新 f[i][j] 为所有可能的切割点 k 中成本最小的值。
    • 注意:当 i == j 时,表示没有切割点,成本为 0;否则,初始化 f[i][j] 为 INT_MAX,表示一个非常大的数,用于后续取最小值。
  5. 返回结果
    • 最后,f[1][cutsSize] 存储了从 tmp[0] 到 tmp[cutsSize + 1](即整个木棍)的最小切割成本。
    • 释放 tmp 数组分配的内存,并返回 f[1][cutsSize]
      int comp(const void* a, const void* b) {
          return *(int*)a - *(int*)b;
      }
      
      int minCost(int n, int* cuts, int cutsSize) {
          qsort(cuts, cutsSize, sizeof(int), comp);
          int* tmp = malloc(sizeof(int) * (cutsSize + 2));
          for (int i = 0; i < cutsSize; i++) {
              tmp[i + 1] = cuts[i];
          }
          tmp[0] = 0, tmp[cutsSize + 1] = n;
          int f[cutsSize + 2][cutsSize + 2];
          memset(f, 0, sizeof(f));
          for (int i = cutsSize; i >= 1; --i) {
              for (int j = i; j <= cutsSize; ++j) {
                  f[i][j] = (i == j ? 0 : INT_MAX);
                  for (int k = i; k <= j; ++k) {
                      f[i][j] = fmin(f[i][j], f[i][k - 1] + f[k + 1][j]);
                  }
                  f[i][j] += tmp[j + 1] - tmp[i - 1];
              }
          }
          free(tmp);
          return f[1][cutsSize];
      }
      

你可能感兴趣的:(c语言,开发语言)