zoukankan      html  css  js  c++  java
  • 木板切割问题(二)——动态规划

    一、问题引入

    有一根长度为L(L < 1000)的木棍,还有n(n < 50)个切割点的位置(按照从小到大排列)。你的任务是在这些切割点的位置处把棍子切成n+1份,使得总费用最小。每次切割的费用等于被切割的木棍长度。

    二、问题分析

    这个问题很像前面的栅栏维修(给定n个木棍的长度,切割点任意),这道题目相当于给定n+1个木棍的长度,且切割点固定。之前的贪心法就不能适用,因为用贪心法需要切割的点不一定是给定的切割点。我们必须换一种思路了。

    n的规模非常小,可以考虑枚举切割点,但直接枚举所有的切割顺序肯定太大,可以考虑动态规划,枚举切割第一刀的位置。

    设d(i,j)为切割小木棍i~j的最优费用,则d(i,j) = min{(d(i,k),d(k,j)) | i < k < j} + a[j] - a[i],其中a[j] - a[i]代表第一刀的费用。

    注意,这里i,j都是表示切割点的位置,而不是木棍的序号,这样比较方便。

    三、代码实现

     1 #include<stdio.h>
     2 #include<iostream>
     3 #include<algorithm>
     4 #include<cstring>
     5 using namespace std;
     6 
     7 const int INF = 0x3f3f3f3f;
     8 const int maxl = 1000 + 10;
     9 const int maxn = 50 + 10;
    10 int L, n, cutp[maxn];
    11 int d[maxn][maxn];    //d[i][j]表示切割小木棍i-->j的最小费用,i,j表示的是切割点,d[0][n + 1]为所求
    12 
    13 void slove()
    14 {
    15     for (int i = n + 1; i >= 0; i--)        //注意循环顺序,这里必须是从大到小
    16         for (int j = i; j <= n + 1; j++)    //这里必须从小到大,这个观察状态转移方程就可以了
    17         {
    18             d[i][j] = (i + 1 == j ? 0 : INF);
    19             for (int k = i + 1; k < j; k++)
    20                 d[i][j] = min(d[i][j], d[i][k] + d[k][j] + cutp[j] - cutp[i]);
    21         }
    22     printf("The minimum cutting is %d.
    ", d[0][n + 1]);
    23 }
    24 
    25 int main()
    26 {
    27     while (scanf("%d", &L) == 1 && L)
    28     {
    29         scanf("%d", &n);
    30         for (int i = 1; i <= n; i++)
    31             scanf("%d", &cutp[i]);
    32 
    33         //左边界编号为0,右边界为 n + 1
    34         cutp[0] = 0; cutp[n + 1] = L;
    35 
    36         slove();
    37     }
    38     return 0;
    39 }

    四、总结

    这种解法,状态有O(n2),每种状态有O(n)个决策,时间复杂度为O(n3)。据说可以用四边形不等式优化到O(n2),以后会了再补充吧。

  • 相关阅读:
    装饰器模式
    mockups 安装
    单例设计模式
    css优先级问题
    GPU的nvadiasmi解析
    conda配置镜像并安装gpu版本pytorch和tensorflow2
    索引的优化
    [转]必须掌握的八个【cmd 命令行】
    BDE莫名的不自动COMMIT问题
    窗体控件笔记
  • 原文地址:https://www.cnblogs.com/lfri/p/9458060.html
Copyright © 2011-2022 走看看