LeetCode343 整数拆分
给定一个正整数 n,将其拆分为至少两个正整数的和,并使这些整数的乘积最大化。 返回你可以获得的最大乘积。
输入: 2
输出: 1
解释: 2 = 1 + 1, 1 × 1 = 1。
题解
1.明确dp[i] [j]表示什么:
首先,将问题转换为完全背包问题:
正整数集合[1…n - 1],体积为i, 价格为i,用这些正整数(每个正整数可选用多次)去构成正整数n。
dp[i] [j]表示用以 i为结尾的正整数集合构成正整数j所用的最大价格乘积。
2.根据题意确定递推关系:
dp[i] [j] = max{ dp[i] [j - i] * i, dp[i - 1] [j] }
3.优化:
使用一个滚动的一维数组dp[j]来表示上面的二维数组dp[i] [j],即:
for (int i = 1;i <= n - 1; ++i)
{
for (int j = i; j <= n; ++j)
{
dp[j] = max(dp[j], dp[j - i] * i);
result = max(result, dp[j]);
}
}
说明:这道题可以看作是一个类完全背包问题,即每个正整数可选用多次,所以在考虑“选i”这个策略时,正需要可能已选入i的子结果dp[i] [j - i],故按照j = i … n正序遍历
4.确定初始条件:
规定构成0的价格为1,即:
dp[0] = 1
class Solution
{
public:
int integerBreak(int n)
{
vector<int> dp(n + 1, INT_MIN);
dp[0] = 1;
int result = INT_MIN;
for (int i = 1;i <= n - 1; ++i)
{
for (int j = i; j <= n; ++j)
{
dp[j] = max(dp[j], dp[j - i] * i);
result = max(result, dp[j]);
}
}
return result;
}
};