准备找工作,开始刷题,牛客剑指offer
链接:https://www.nowcoder.com/questionTerminal/57d85990ba5b440ab888fc72b0751bf8?f=discussion
给你一根长度为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。
输入描述:
输入一个数n,意义见题面。(2 <= n <= 60)
输出描述:
输出答案。
示例1
输入
8
输出
18
题解:
方法一:
- 贪心算法:这种想法比较巧妙,尽量把大于5的数分解成3的乘积,如果剩下的长度为4,则把4分解成2和2,因为3*1<2*2
方法二:
- 利用动态规划,需要O(n^2)时间和O(n)空间,也就是利用一个表,储存长度为1~n绳子的最大乘积。
代码:
#include<bits/stdc++.h>
using namespace std;
//贪心
int cutRope1(int number) {
if(number == 2)
return 1;
if(number == 3)
return 2;
int a = number % 3; //计算余数
int b = number / 3; //计算有多个3
if(a == 0) //余数为0时,所有3乘积即是结果; 例如9: 3*3*3
return pow(3,b);
else if(a == 1) //余数为1时,应将1*3分解成2*2; 例如10: 3*3*2*2
return pow(3,b-1) * 4;
else if(a == 2)
return pow(3,b) * 2; //余数为2时,直接将结果*2; 例如11: 3*3*3*2
}
//动态规划
int cutRope2(int number) {
int dp[65];
dp[1] = 1;
dp[2] = 2;
dp[3] = 3;
int res = -1;
for(int i = 4; i <= number; i++) {
for(int j = 1; j <= i/2; j++) { //计算1到i的一半,因为后一半计算的值相同
res = max(res,dp[j]*dp[i-j]); //比如dp[1]*dp[4-1] 和 dp[3]*dp[4-3]
}
dp[i] = res;
}
return dp[number];
}
int main()
{
int n,m;
cin >> n;
while(n--) {
cin >> m;
cout << cutRope2(m) << endl;
}
return 0;
}
好了,总结一下吧;这道题我也做了很久,最后找了找规律,利用动态规划做出来;然后看题解发现贪心方法是真的挺妙的,相比动态规划更容易理解,并且时间、空间方面都略胜动态规划。嗯嗯…刷其它题去了