用动态规划和贪心算法求解割绳子问题

题目描述
给你一根长度为n的绳子,请把绳子剪成整数长的m段(m、n都是整数,n>1并且m>1,m<=n),每段绳子的长度记为k[1],…,k[m]。请问k[1]x…xk[m]可能的最大乘积是多少?例如,当绳子的长度是8时,我们把它剪成长度分别为2、3、3的三段,此时得到的最大乘积是18。
输入描述:
输入一个数n,意义见题面。(2 <= n <= 60)
输出描述:
输出答案。
示例1
输入
复制
8
输出
复制
18

这是一题典型的动态规划问题,可以写出递推公式如下
f(n)=
1 , n=2
2 , n=3
max{ f(1)*f(n-1),f(2)*f(n-2),…,f(i)f(n-i)},n=其他
代码如下所示,各位记得看注释

public int cutRope(int number)
    {
        //不在输入限定范围,返回-1
        if(number<2 || number>60)
        {
            return -1;
        }
        //绳长为2时候,可以分为1,1,返回1
        if(number==2)
        {
            return 1;
        }
        //绳长为3的时候,可分为1,2,返回3
        else if(number==3)
        {
            return 2;
        }
        //当绳子长度大于等于4的时候
        else
        {
            //声明数组,array[i]表示长度为i的绳子的乘积的最大值
            //定义时,为了使得数组的标号和长度信息一致,设定数组的长度为输入的绳子长度+1
            int[] array=new int[number+1];
            array[0]=0;//绳子长度为0,没有长度,乘积为0
            array[1]=1;//绳长为1,乘积为1
            array[2]=2;//绳长为2,分成1,1,乘积为1
            array[3]=3;//绳长为3,分成1,3,最大乘积为3
            int maxNum=0;//当前绳长时取得的最大值
            for(int i=4;i<=number;i++)
            {//i表示的是输入的绳子长度,由于之前计算过绳长为1,2,3的情况,故这次直接从4开始
                for(int j=1;j<=i/2;j++)
                {//j表示切开的地方,由于array[5]*array[6]和array[6]*array[5]是一致的,j只需要一种情况就行,故j<=i/2
                    int a=array[j]*array[i-j];
                    if(a>maxNum)
                    {
                        maxNum=a;
                    }
                }
                array[i]=maxNum;//记录当前绳子长度为i时可以取到的最大乘积
            }
            return array[number];//返回要求的最大值
        }
    }
    

可能有人会疑惑(其实就是我自己),为什么在代码中求了每一个array[i]的值而不是直接求array[number],这样做不是耗费性能吗

原因是,如果直接求取array[number],在算法中也会进行拆分,仍然会用到array之前的值,所以必须把array[number]之前的值求出来,才能够求我们要的array[number]
割绳子问题还可以用贪心算法求解,代码如下:

    int cutRope(int number) {
        if(number==2)
        {
            return 1;
        }
        if(number==3)
        {
            return 2;
        }
        if(number>=4)
        {
            int x=number%3;
            int y=number/3;
            if(x==0)
            {
                return pow(3,y);
            }
            else if(x==1)
            {
                return 2*2*pow(3,y-1);
            }
            else if(x==2)
            {
                return 2*pow(3,y);
            }
        }
    }

你可能感兴趣的:(算法题专栏)