剑指offer——15剪绳子

题目描述

给你一根长度为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。
 
题解:
  边界要注意一下,因为题目要求一定要分成至少两段,故,当n=1 ->1*0;   n=2  -> 1*1;   n=3   ->   2*1
  两种方法进行求解
  
动态规划:
  首先定义函数(n)为把长度为n的绳子剪成若干段后各段长度乘积的最大值。在剪第一刀的时候,我们有n-1种可能的选择,也就是剪出来的第一段绳子的可能长度分别为1,2….n-1。因此f(n) = max(f(i) * f(n-i))。
   
 1 class Solution {
 2 public:
 3     int cutRope(int number) {
 4         if (number <= 1)return 0;
 5         if (number < 5)return (number / 2)*(number - number / 2);//因为至少要分为2段
 6         vector<int>dp(number + 1, 0);
 7         dp[0] = 0, dp[1] = 1, dp[2] = 2, dp[3] = 3;
 8         int maxN = 0;
 9         for (int i = 4; i <= number; ++i)
10         {
11             maxN = 0;
12             for (int j = 1; j <= i / 2; ++j)
13             {
14                 int temp = dp[j] * dp[i - j];
15                 maxN = maxN > temp ? maxN : temp;
16                 dp[i] = maxN;
17             }
18         }
19         return dp[number];
20     }
21 };
 
贪婪算法:
  如果我们按照如下的策略来剪绳子,则得到的各段绳子的长度的乘积将最大:当n≥5时,我们尽可能多地剪长度为3的绳子;当剩下的绳子长度为4时,把绳子剪成两段长度为2的绳子。
  为什么要剪成3,这是个数学证明,详细请看书
  
 1 class Solution {
 2 public:
 3     int cutRope(int number) {
 4         if (number <= 1)return 0;
 5         if (number < 5)return (number / 2)*(number - number / 2);//因为至少要分为2段
 6         int n3 = number / 3;//3的个数
 7         if (number % 3 == 1)//最后剪的一段为4时,不要剪成3-1,要剪成2-2
 8             n3--;
 9         int n2 = (number - 3 * n3) / 2;//2的个数
10         return pow(3, n3)*pow(2, n2);
11     }
12 };
 
  

猜你喜欢

转载自www.cnblogs.com/zzw1024/p/11656418.html