【题目描述】
给你一根长度为n的绳子,请把绳子剪成整数长的m段(m、n都是整数,n>1并且m>1,m<=n),每段绳子的长度记为k[1],…,k[m]。请问k[1]x…xk[m]可能的最大乘积是多少?例如,当绳子的长度是8时,我们把它剪成长度分别为2、3、3的三段,此时得到的最大乘积是18。
【解法】
1.递归法
//n>1,m>1,m<=n; 且每段都是整数长
//意思就是说,每一段的长度都大于等于1,且,至少要切一刀,可以切 1,2,3,...n-1刀,不一定是几刀。
//当切n-1🔪时,就是n个1;
class Solution {
public:
int back_track(int n) {
if(n<=4){
return n;
}
int ret = 0;
for (int i = 1; i < n; ++i) {
ret = max(ret, i * back_track(n - i));//重点在这里:i*back_track(n-i)
}
return ret;
}
int cutRope(int number) {
if (number == 2) {//只能切一刀1*1
return 1;
}
else if (number == 3) {//切1或2刀,1*1*1 / 2*1
return 2;
}
return back_track(number);
}
};
2.记忆法递归
//减少一些重复计算
class Solution {
public:
int back_track(int n, vector<int> &mark) {
if (n <= 4) {
return n;
}
// 在方法一的基础上添加
if (mark[n] != -1) {
return mark[n];
}
int ret = 0;
for (int i = 1; i < n; ++i) {
ret = max(ret, i * back_track(n - i,mark));
}
// 添加部分
return mark[n] = ret;
}
int cutRope(int number) {
if (number == 2) {
return 1;
}
else if (number == 3) {
return 2;
}
// 添加部分
vector<int> mark(number+1, -1);
return back_track(number, mark);
}
};
3.动态规划
class Solution {
public:
int cutRope(int number) {
if (number == 2) {
return 1;
}
else if (number == 3) {
return 2;
}
vector<int> f(number + 1, -1);
for (int i = 1; i <= 4; ++i) {
f[i] = i;//1 2 3 4
}
for (int i = 5; i <= number; ++i) {//5->number
for (int j = 1; j < i; ++j) {
f[i] = max(f[i], j * f[i - j]);
}
}
return f[number];
}
};