动态规划之钢条切割

问题导入

假定某公司购买长钢条,将其切割为短钢条进行出售(切割工序本身没有成本支出)。考虑求出最佳的切割方案。

出售一段长度为i的钢条价格如下表:

长度i 价格p
1 1
2 5
3 8
4 9
5 10
6 17
7 17
8 20
9 24
10 30

时间复杂度

长度为n的钢条共有2的n-1次方种不同的切割方案,因为在距离钢条左端i处,总是可以选择切割或不切割。所以普通方法(递归)解决此问题的时间复杂度为2的指数级别。

普通方法效率很低,是因为它反复求解相同的子问题

动态规划则仔细安排求解顺序,对每个子问题只求解一次,并将结果保存下来。如果随后再次需要求解此子问题的解,只需查找保存的结果,而不必重新计算。因此,动态规划是付出额外的内存空间来节省计算时间。而时间上的节省可能是非常巨大的。

动态规划原理

动态规划与分治方法相似,都是通过组合子问题的解来求解原问题。

适合使用动态规划方法求解的最优化问题应该具备两个要素:

1.最优子结构:如果一个问题的最优解包含其子问题的最优解,就称此问题具有最优子结构轻型纸。

2.子问题重叠:问题的递归算法会反复地求解相同的子问题,而不是一直产生新的子问题。

问题求解

public class Cut {
    public static void main(String[] args) {
        //钢条价格数组
        int[] p = {1,5,8,9,10,17,17,20,24,30};
        method(p, 10);
    }
    public static void method(int[] p, int n){
        //结果数组
        int[] r = new int[n+1];
        //切割方式数组
        int[] s = new int[n+1];
        for(int j = 1;j <= n;j++){
            int q = -1;     //此处-1的作用是"无穷小"
            for(int i = 1;i <= j;i++){
                if(q < p[i-1]+r[j-i]){
                    q = p[i-1]+r[j-i];
                    s[j] = i;   //表示长度为j时,被切割后的左部分长度为i,而右部分如何切割则递归查找s数组
                    r[j] = q;   //长度为j时的最大收益值
                }
            }
        }
        for (int count = 0;count <= n;count++){
            System.out.println(r[count]);
            System.out.println(s[count]);
        }
    }
}

算法主体部分为两层for循环,因此用动态规划解决此问题的时间复杂度为n的平方。

猜你喜欢

转载自www.cnblogs.com/cky-2907183182/p/12184593.html