剪绳子的几种解法 — C++实现

题目描述

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

牛客网题目链接

动态规划求解

我们定义函数 f ( n ) f(n) f(n)为把长度为n的绳子剪成若干段后乘积的最大值

f ( n ) = m a x ( f ( i ) − f ( n − i ) ) f(n)=max(f(i)-f(n-i)) f(n)=max(f(i)f(ni))

  • 把长度为n的绳子剪为长度为i和长度为n-i的两端,然后再求子问题 f ( i ) f(i) f(i) f ( n − i ) f(n-i) f(ni)(i=1,2,...,n-1)

即:一个问题可以分解为子问题,要使得该问题最优,则子问题先要实现最优,因此我们可以使用动态规划的思路去求解

原问题从上到下使用递归法求解,动态规划的核心是填表,先求解子问题,然后自下而上求解,最终得到原问题的解

求解代码

class Solution {
public:
    int cutRope(int number) {
        if(number<4)return number;
        else{
            int *tab =new int[number+1];//表格数组
            int i,j;
            //以下为填表过程
            tab[0]=0;tab[1]=1;tab[2]=2;tab[3]=3;
            for(i=4;i<=number;i++){
                tab[i]=0;
                for(j=1;j<=i/2;j++){
                    if(tab[i]<tab[j]*tab[i-j])
                        tab[i]=tab[j]*tab[i-j];
                }
            }
            return tab[number];//表中最后一个即为所求
        }
    }
};
运行时间:3ms

占用内存:608k

贪心法求解

尽可能地剪出长度为3的子段,但当最后一段所剩长度为4时,将其剪为2*2的两段落,因为2*2 > 3*1

PS:关于为何剪为3的子段的数学证明博主还没有想到如何用通俗易懂的方式讲解(可参考《剑指Offer》),欢迎大佬留言指教

求解代码

class Solution {
public:
    int cutRope(int number) {
        if(number<5)return number;
        if(number%3==1)
            return pow(3,number/3-1)*4;
        else
            return pow(3,number/3)*pow(2,(number%3)/2);
    }
};
运行时间:3ms

占用内存:608k
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
C++中,绳子问题是一个经典的动态规划问题。问题描述为:给定一根长度为n的绳子,要求将其成m段(m>1),每段绳子的长度记为k, k, ..., k[m-1],请问如何绳子使得各段绳子的乘积最大? 解决这个问题的一种常见方法是使用动态规划。具体步骤如下: 1. 定义一个数组dp,其中dp[i]表示长度为i的绳子成若干段后各段绳子长度乘积的最大值。 2. 初始化dp数组,dp和dp都为0,因为长度为0和1的绳子无法断。 3. 从长度为2开始遍历到n,对于每个长度i,计算dp[i]的值。 - 遍历j从1到i-1,表示第一段绳子的长度,可以取值范围为1到i-1。 - 计算第一段绳子长度为j时,剩余绳子的长度为i-j。 - 计算当前情况下的乘积,即j * dp[i-j]。 - 更新dp[i]的值为所有情况中乘积最大的值。 4. 最终dp[n]即为所求的结果,表示长度为n的绳子成若干段后各段绳子长度乘积的最大值。 下面是绳子问题的C++代码示例: ```cpp #include <iostream> #include <vector> using namespace std; int cutRope(int n) { if (n <= 1) { return 0; } vector<int> dp(n + 1, 0); for (int i = 2; i <= n; i++) { for (int j = 1; j < i; j++) { dp[i] = max(dp[i], max(j * (i - j), j * dp[i - j])); } } return dp[n]; } int main() { int n = 8; int result = cutRope(n); cout << "将长度为" << n << "的绳子成若干段后各段绳子长度乘积的最大值为:" << result << endl; return 0; } ```

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值