【剑指offer】剪绳子

题目链接:剪绳子

 

题意:给你一根长度为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。

 

题解:

1、dp做法。每段绳子都能分割成它的乘积。因此,动态转移方程dp[i] = max{dp[i],dp[j] * dp[i-j]}.

这里要注意的是,绳长 = 2 / 3时,它们是必须要分割的(m>1),所以特殊讨论。

len = 2,分割就是 1 1,所以乘积为1。

len = 3,分割就是 1 2,所以乘积为2 。

一旦len>3了,那前面的就相当于是作为len里的分割元素,也就是dp[2]=2,dp[3]=3.

2、贪心。每个数字(>3)都能分解成有n个2和n个3的相加。举例,

4:2+2

5:2+3

6:3+3

7:2+2+3

8:2+2+2+2

 所以我们直接贪心,看数字里含多少个3再去看除去3以后含多少个2。

要考虑一下有4的情况,此时要分解成2+2而不是1+3。因此对于像7,10这种数,做一个特判。

代码:

 1 class Solution {
 2 public:
 3     int dp[105]={0};
 4     int cutRope(int number) {
 5         if(number == 2)    return 1;
 6         if(number == 3)    return 2;
 7         dp[0] = 0; dp[1] = 1;
 8         dp[2] = 2; dp[3] = 3;
 9         for(int i = 4 ;i <= number; i++){
10             for(int j = 1; j <= i/2; j++){
11                 dp[i] = max(dp[i],dp[j]*dp[i-j]);
12             }
13         }
14         return dp[number];
15     }
16 };
17 
18 
19 OR
20 
21 
22 class Solution {
23 public:
24     int cutRope(int number) {
25         if(number == 2)    return 1;
26         if(number == 3)    return 2;
27         int cnt = number/3;    //含3的个数
28         if(number - cnt*3 == 1)    //保证最后有4的情况是2*2
29             cnt--;
30         int cntt = (number - 3*cnt)/2;    //2的个数
31         int ans = pow(3,cnt)*pow(2,cntt);
32         return ans;
33     }
34 };
原文地址:https://www.cnblogs.com/Asumi/p/12431518.html