题目链接
class Solution {
public:
int maxProductAfterCutting(int length) {
int ans=-1;
//感觉有点dp的味道
//每个位置断的话,最大就是左右两边的最大值乘积
int dp[60];//dp[i]表示长度为i的绳子裁剪得到的最大乘积
dp[0]=0;
dp[1]=1;
dp[2]=2;
for(int i=3;i<=length;i++){
int tmp=i;//不分割
for(int j=1;j<i;j++){
tmp=max(tmp,dp[j]*dp[i-j]);
}
dp[i]=tmp;
}
dp[2]=1;//至少要分成2段
dp[3]=2;//至少要分成2段
//dp[4]之后都不会是length本身是最大值
return dp[length];
}
};
自己写的dp对于2和3的情况需要特判,对于≥4之后的绳子,是切割之后能得到最大值,对于2和3,不切才是最大,但是题目要求至少切为2段,因此递推后面的dp[i]时用的dp[2]=2,dp[3]=3,最后再重新赋值回正确答案。
这样不统一的本质原因是理解成了1-i中在j处切一刀之后的最值是两段绳子各自至少2次切割的最大值,也就是用dp[j]*dp[i-j],事实上对于2和3而言,不切割才会是最大的,即 dp[2]=1,dp[3]=2是必须切一刀之后的最大值,对于后面用到2和3,用本身的2和3才对,转化一下状态转移方程就是下面的了
受此启发,其实就是对于0-i,在j处切割之后,左边取不切与切两种选择的最大值,右边取不切与切两种选择最大值,两者乘积就是在j处切割所能达到的最大值了。
class Solution {
public:
int maxProductAfterCutting(int length) {
int ans=-1;
//感觉有点dp的味道
//每个位置断的话,最大就是左右两边的最大值乘积
int dp[60]={0};//dp[i]表示长度为i的绳子裁剪得到的最大乘积
for(int i=2;i<=length;i++){
for(int j=1;j<i;j++){
dp[i]=max(dp[i],max(j,dp[j])*max(i-j,dp[i-j]));
}
}
return dp[length];
}
};