Java 剑指offer 面试题14:剪绳子

版权声明:本文为博主原创文章,转载请标明出处。 https://blog.csdn.net/weixin_43014205/article/details/87647436

题目:给你一根长度为n的绳子,请把绳子剪成m段 (m和n都是整数,n>1并且m>1)每段绳子的长度记为k[0],k[1],…,k[m]. 请问k[0]k[1]…*k[m]可能的最大乘积是多少?例如,当绳子的长度为8时,我们把它剪成长度分别为2,3,3的三段,此时得到的最大乘积是18.

采用动态规划解决此问题

分析:采用动态规划解决问题的特点:

1.假设第一刀剪在长度为i(0<i<n)的位置,于是把绳子剪成了长度为 i 和 n-i 的两段,我们想要得到整个问题的最优解f(n),那么要用同样的方法将 i 和 n-i段切割成若干段。使他们各自剪出的每段绳子乘积最大。

也就是说,整体问题的最优解是依赖各个子问题的最优解

 f(4)=max{f(1)f(3), f(2)f(2)}
 f(5)=max{f(1)f(4), f(2)f(3)}
  ...
 f(n)=max{f(1)f(n-1), f(2)f(n-2), f(3)f(n-3), ..., f(i)(fn-i), ...}

因为需要保证f(i)f(n-i)不重复,就需要保证i<=n/2,这是一个限制条件,求1~n/2范围内的乘积,得到最大值

得到状态转移方程:

f(n)=max(f(i)xf(n-i)),其中0<i<n

/**
 * 动态规划
 *
 * f(n) = max(f(i)*f(n-i))
 */
public class demo1 {
    public int cutScopeSolution(int length){
        if(length<2){
            return 0;
        }else if(length==2){
            return 1;
        }else if(length==3){
            return 2;
        }
        //创建辅助数组  存储  已产生的最小值
        int[] arr = new int[length + 1];
        arr[0]=0;
        arr[1]=1;
        arr[2]=2;
        arr[3]=3;
        /**
         *
         *  这些情况下,不剪的时候长度比剪的时候长,所以作为初始条件
         *  这些都是子问题最优解,因为是子问题,所以这些情况可以不剪,因为可以看成它是分割后的一部分
         */
        int max = 0;
        for(int i = 4;i<=length;i++){
            max = 0;
            for(int j = 1;j<=i/2;j++){
                int temple = arr[j]*arr[i-j];
                if(max<temple){
                    max=temple;
                }
                arr[i]=max;
            }
        }
        return arr[length];
    }
}


 

猜你喜欢

转载自blog.csdn.net/weixin_43014205/article/details/87647436