【题目描述】
AcWing 25. 剪绳子
DFS
class Solution {
int ans = 0;
//t 当前枚举到了第几段 m 表示总段数 n表示绳子剩余长度 res 乘积
public void dfs(int t, int m, int n, int res){
if( n < 0 || t > m) return;
//System.out.println(t +" "+ m +" "+n +" "+ res);
if( t == m){//段数符合
if(n == 0 && res > ans) ans = res;
return;
}
//枚举每一段的可能长度
for(int x = 2; x <= n/ (m - t) + 1; x ++)
dfs(t + 1, m, n - x, res * x);
}
public int maxProductAfterCutting(int length)
{
//枚举段数m[2, length - 1] dfs(0, 2, length, 1);
for(int m = 2; m < length ; m ++){
//段数m确定了,要保证其m个段乘积最大 其最大可枚举的段长度也就确定了 为 n / m + 1
dfs(0, m, length, 1);
}
return ans;
}
}
【思路】
贪心选择
将一个大整数N分解成n1, n2, n3 , …… ni ,要使得其乘积最大,则:
ni < 5,数字2的个数不超过2,余下的全是3。
证明:
1、如果 ni > 5, (ni - 3)*3 = 3 * ni - 9 > ni 所以如果有ni > 5,那么一定可以拆成包含3的形式
2、如果 ni == 4,那么可以拆成两个2
3、ni 不为1 且 ni>=2
4、如果有三个以上的2,那么 3×3>2×2×2,所以替换成3乘积更大;
class Solution {
public int maxProductAfterCutting(int n)
{ //特判 要求段数是大于2的
if( n <= 3) return (n - 1);
int res = 1;
// 4 7 10
if(n % 3 == 1){//可以拆成两个2
n -= 4;
res *= 4;
}else if(n % 3 == 2){//拆一个2
n -= 2;
res *= 2;
}
while(n > 0){
n -= 3;
res *= 3;
}
return res;
}
}