剑指offer_剪绳子(C++_动态规划/图解贪心算法)

原题链接

在这里插入图片描述

动态规划

1.思路

可以分析出来,因为题目要求必须剪。当绳子的长度小于2的时候不能剪了,这里返回0。当长度为2时只能1×1,乘积为1。当长度为3时最大乘积为1×2=2。

当长度>3时假设长度为n,在剪第一刀时有n-1种情况
假设一刀将绳子剪为i长与n-i长,乘积最大为F(n)=F(i)*F(n-i)
这个式子为一个递归式,其中有大量的重复计算。
所以我们从下往上开始记录,定义一个数组Cout,数组的下标值对应的是绳子的长度,下标对应的值为绳子在是下标长度时的最大乘积(最优解)。
所以F(n)=F(i)*F(n-i)可以写为max(Cout[i]*Cout[n-i])

2.动态规划C++代码

class Solution {
public:
    int cutRope(int number) {
        if(number<2)
            return 0;
        if(number==2)
            return 1;
        if(number==3)
            return 2;
        int* cout=new int[number+1];//多存放number=0情况
        cout[0]=0;
        cout[1]=1;
        cout[2]=2;
        cout[3]=3;
        for(int i=4;i<=number;i++)
        {
            int max=0;
            for(int j=1;j<=i/2;j++)//循环找最大乘积值
            {
                if(max<cout[j]*cout[i-j])
                {
                    max=cout[j]*cout[i-j];
                }
            }
            cout[i]=max;
        }
        return cout[number];
    }
};

3.代码注意

为什么当绳子长度<2时乘积为0,这里cout数组cout[0]=0,cout[1]=1

解:
能运行到cout数组这里说明其长度一定大于3
这里cout[1]=1不是说长度为1的绳子最大乘积为1,而是指如果剪后出现长度为1的绳子就不剪了。同理cout[3]表明当剪后出现长度为3的绳子就不剪了,如果再剪成1和2乘积为2<3就不是最优解了。
eg:长度为4的绳子先计算的为cout[1]×cout[3]相当于剪成了长度为1和长度为3的绳子对应数组下标的乘积值为1×3=3。

贪心算法

1.思路

同理:因为题目要求必须剪。当绳子的长度小于2的时候不能剪了,这里返回0。当长度为2时只能1×1,乘积为1。当长度为3时最大乘积为1×2=2。当绳子长度为4时最大乘积为2×2=4

当绳子长度>=5时

①证明一

我们发现当剪下的两条绳子长度的乘积大于等于其本身才有剪的意义
即i×(n-i)>=n(其中n>=5)
在这里插入图片描述
由上面可知我们要尽量选择剪出长度为2或者3的绳子,可以使最后的乘积最大,优先剪出长度为3的绳子。

②证明二

在绳子长度>=时5我们剪绳子最优解为:
一段长度为i与n-i的乘积要大于等于(i-1)与(n-i+1)同时还要大于等于(i+1)与(n-i-1)的乘积,即剪掉长度i是最优解

在这里插入图片描述

2.C++贪心算法代码

class Solution {
public:
    int cutRope(int number) {
        if(number<2)
            return 0;
        if(number==2)
            return 1;
        if(number==3)
            return 2;
        int CoutPow3=number/3;//计算可以切出几个长度为3的绳子
        if(number-3*CoutPow3==1)
    //如果切到最后长度为4,单独处理长度为4的绳子,切成2*2,最大乘积为4
        {
            CoutPow3--;
            return pow(3,CoutPow3)*4;
        }
        if(number-3*CoutPow3==2)
     //切到最后长度为2,这时不需要再切了长度为2
        {
            return pow(3,CoutPow3)*2;
        }
     //正好可以切成整数个长度为3的绳子
        return pow(3,CoutPow3);
    }
};

  • 11
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 6
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

NUC_Dodamce

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值