题目描述
给你一根长度为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)
输出描述:
输出答案。
输入
8
输出
18
思路:将一个正整数拆分为若干个正整数的和,使得这些正整数的乘积最大,那么
1.拆的个数尽可能多,但不要拆成1,
2.且拆成的数不要大于4(因为5<2*3,6<3*3,...),
3.并且拆成的数2的个数不要超过2个(因为2*2*2<3*3)
class Solution { public: int cutRope(int number) { if(number == 2) return 1; if(number==3) return 2; int rem = number % 3; int quo = number / 3; if(rem == 0){ return pow(3,quo); }else if(rem == 1){ return pow(3,quo-1)*2*2; }else{ return pow(3,quo)*2; } } };
动态规划法:
dp[i]表示绳长为i时对应的最大值
那么dp[i] =max {不切话乘积值,dp[j]*dp[i-j]}(1 <= j <= i/2)
public int cutRope(int target) { if(target==2) return 1; if(target == 3) return 2; int[] dp = new int[target+1]; int max = 0; dp[1] = 1; dp[2] = 2; dp[3] = 3; for(int i = 4;i<=target;i++){ for(int j=1;j<=i/2;j++){ max = Math.max(max,dp[j]*dp[i-j]); } dp[i] = max; } return dp[target]; }
讨论区大神解法:
public int cutRope(int target) { //定义最大值数组,题目要求最大长度是 60 int[] dp = new int[62];// 0 - 61 //给定初始值 dp[1] = 1; //对于 2 -> target - 1 打表 做最优分法(不一定是二分,可以一分) for (int i = 2; i <= target; i++) { // max 初始化为 一分的结果(本身) int max = i; // 对于最少二分做解 for (int j = 1; j <= i / 2; j++) { max = Math.max(max, dp[j] * dp[i - j]); } // 写入结果 dp[i] = max; } // 定义target的初始值 return dp[target]; }