题解
动态规划:
- 对于任意 n n n,分解为 f 1 , f 2 , f 3 . . . f k f_1,f_2,f_3 ... f_k f1,f2,f3...fk。对于任意 f i , i ∈ [ 1 , k ] f_i,i∈[1, k] fi,i∈[1,k] 继续拆分后,最后都是乘积关系,所以满足无后效性,可以使用动态规划解决。
- 设 d p [ i ] dp[i] dp[i] 为长度为 i i i 的绳子分解最大值。
- 那么状态转移方程: d p [ i ] = m a x ( d p [ i ] , d p [ i − j ] ∗ d p [ j ] ) , d ∈ [ 1 , i / 2 ] dp[i] = max(dp[i], dp[i-j] * dp[j]), d∈[1, i/2] dp[i]=max(dp[i],dp[i−j]∗dp[j]),d∈[1,i/2]
贪心:
- 其实很好发现:
- n < = 3 n <=3 n<=3 的时候,不拆分是最好的,
- n = = 4 n==4 n==4 的时候,拆分|不拆分是一样的,
- n > = 5 n >= 5 n>=5 的时候,拆分是最好的。
- 那么也就是说,最后一定会拆分的结果一定是小于等于 4 4 4 的。
- 对于 4 4 4,一定是拆分为 2 ∗ 2 2*2 2∗2 是最优解。
- 那么最后就是在 2 2 2 和 3 3 3 中选择。
- 当 n > = 5 n>=5 n>=5 时, 3 ∗ ( n − 3 ) > = 2 ∗ ( n − 2 ) 3*(n-3)>=2*(n-2) 3∗(n−3)>=2∗(n−2),那么就尽可能的按 3 3 3 分割。
- 最后剩下的如果是 2 2 2,就直接乘进去,如果是 1 1 1,那就取出一个 3 3 3 组成 2 ∗ 2 2*2 2∗2
AC-Code
DP:
class Solution {
public:
int cutRope(int number) {
if(number < 2) return 0;
if(number == 2) return 1;
if(number == 3) return 2;
int *dp = new int[number + 1];
memset(dp, 0, sizeof(dp));
dp[1] = 1; dp[2] = 2; dp[3] = 3;
for(int i = 4; i <= number; ++i)
for(int j = 1; j <= i / 2; ++j)
dp[i] = max(dp[i], dp[i - j] * dp[j]);
int ans = dp[number];
delete[] dp;
return ans;
}
};
贪心:
class Solution {
public:
int cutRope(int number) {
if(number < 2) return 0;
if(number == 2) return 1;
if(number == 3) return 2;
return number % 3 == 1 ? pow(3 , (number/3 - 1)) * 4 : pow(3, (number / 3)) * 2;
}
};