剪绳子

情到浓时终转凉″ 提交于 2020-03-06 18:53:30

剪绳子

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

思路:
这题有两种解题思路,一种动态规划另一种是贪心。

动态规划:
因为试求绳子分解后的最大乘积,是求最优解,这符合动态规划的第一个特点。该问题的最优解依赖于小问题的最优解,符合动态规划的第二个特点。往下分解的时候有很多重复的小问题,这是动态规划的第三个特点。该题都符合,所以可以使用动态规划。
一开始先将一些特殊情况输出来,因为题目是至少要剪一到,所以长度小于2的时候返回0,没得剪。长度为2的时候返回1,长度为3的时候返回。这就是特殊值。以为4的分解有两种情况。虽然可以看出最优解,但我没有吧他归为特殊情况。建一个最优解数组,从开始往下算,算到绳子长度为n时就可以停止了。注意一点的是在剪的时候,最长剪到一半就可以了,如果超过一半,其实会和前面的重复。

贪心:
这题的贪心策略是尽量剪绳子的长度为三,剩下4的时候剪为两段2;
当你n>=5时,2*(n-2)>n并且3*(n-3)>n,当绳子长度大于5的时候就尽量剪长度为3和2的绳子,
并且3*(n-3)>2*(n-2),所以尽量剪3,不够则剪2.

动态规划:

//动态规划
        public  int cutRope1(int target) {
            if(target<2) return 0;
            else if(target==2) return 1;
            else if(target==3) return 2;

            int p[] = new int[target+1];
            p[0]=0;
            p[1]=1;
            p[2]=2;
            p[3]=3;
            for(int i=4;i<p.length;i++){
                int max=0;
                for(int j=1;j<=i/2;j++){
                    int pmax=p[j]*p[i-j];
                    if(max<pmax){
                        max=pmax;
                    }
                }
                p[i]=max;
            }
            return p[target];
        }

贪心:

//贪心
        public  int cutRope2(int target) {
            if(target<2) return 0;
            else if(target==2) return 1;
            else if(target==3) return 2;

            int num3=target/3;
            if(target%3==1){
                num3--;
            }
            int num2=(target-num3*3)/2;
            int max=1;
            for(int i=0;i<num3;i++){
                max=max*3;
            }
            for(int j=0;j<num2;j++){
                max=max*2;
            }
            return max;
        }
标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!