链接:https://www.nowcoder.com/questionTerminal/25b04bac36b840ab93f6fd913d1c7247
来源:牛客网
编程题
【问题描述】
给你一根长度为n的绳子,请把绳子剪成m段 (m和n都是整数,n>1并且m>1)每段绳子的长度记为k[0],k[1],...,k[m].请问k[0]*k[1]*...*k[m]可能的最大乘积是多少?
【要求】
【数据输入】绳子长度,一个整型数n(n>1)
【数据输出】把绳子剪成m段后, 可能的最大乘积数,也是一个整型数
【样例输入】
绳子的长度n=9
【样例输出】
我们把它剪成长度分别为3,3,3的三段,此时得到的最大乘积是3*3*3=27
思路:
动态规划:
从小到大,10可以由0~5推出来,9可以由0~9/2推出来
这里就是动态方程必须是二维的,时间复杂度为O(n*n)
dp初始化为dp【i】=i。但是如果长度是3,只能返回2
因为题目要求是必须切一下,所以4-----2*2是4
3------2*1是2,其实在动态规划过程中,必须把dp【3】设置为3
扫描二维码关注公众号,回复:
2644996 查看本文章
贪婪算法:
3的倍数最大,虽然我也不知道怎么推导,但就是这样
然后分为0~4和5以上的两种
5以上的先除以3,剩下的可以依照0~4来做
为什么把4单独提取出来?
因为题目要求是必须切一下,所以4-----2*2是4
3------2*1是2,其实在动态规划过程中,必须把dp【3】设置为3
而我们贪婪算法中,不需要初始化,但是如果7%3==1.
这时3*3*1不是最大的。就是因为4=2*2>3*1.
ok
调试代码:
#include <iostream>
using namespace std;
int maxResultOfCut(int len)//动态规划
{
if(len==0)
return 0;
if(len==1)
return 1;
if (len==2)
return 1;
if(len==3)
return 2;
int Res=0;
int *dp=new int [len+1]();
for(int i=0;i<=len;i++)
dp[i]=i;//注意这里的初始化与上面返回的区别
for(int i=4;i<=len;i++)
{
for(int j=1;j<=i/2;j++)
{
dp[i]=max(dp[i-j]*dp[j],dp[i]);
//Res=max(dp[i-j]*dp[j],Res);//Res=max(dp[i-j]dp[j],Res);
}
}
Res=dp[len];
delete dp;
return Res;
}
int maxResultOfGreedy(int len)
{
int Res=0;
if(len<2) return 0;
if(len==2) return 1;
if(len==3) return 2;
int timeof3=len/3;
if(len%3==1)//注意这里必须判断余数为1的情况
timeof3--;
return (int)pow((float)3,timeof3)*(int)pow((float)2,(len-timeof3*3)/2);
}
int main()
{
int n=10;
//for(int n=0;n<=100;n++)
//{
cout<<maxResultOfCut(n)<<endl;
cout<<maxResultOfGreedy(n)<<endl;
//}
return 0;
}