您的位置:首页 > 其它

Leetcode - Dynamic Programming - 343. Integer Break(划分整数得到最大乘积)

2016-08-22 18:57 501 查看

1. Problem Description

Given a positive integer n, break it into the sum of at least two positive integers and maximize the product of those integers. Return the maximum product you can get.

 

For example, given n = 2, return 1 (2 = 1 + 1); given n = 10, return 36 (10 = 3 + 3 + 4).

 

Note: You may assume that n is not less than 2 and not larger than 58.

给你一个整数num(2<=num<=58),把这个数划分成几个数的和,求这几个数的乘积的最大值。

2. My solution1(回溯法,超时)

最好想的方法,把这个数划分成从2到num个数(记为cnt),并且分别枚举cnt个数分别会是什么,把他们求一下乘积,计算最大值即可。

 

可想而知这种方法必然会超时,不过我们可以利用它来找出规律。

class Solution
{
public:
int ans;
void dfs(int num,int cnt,int curproduct)
{
if(cnt==1)
{
if(curproduct*num>ans)
ans=curproduct*num;
return ;
}
for(int i=1; i<=num; i++)
dfs(num-i,cnt-1,curproduct*i);
}
int integerBreak(int n)
{
ans=1;
for(int cnt=2; cnt<=n; cnt++)
dfs(n,cnt,1);
return ans;
}
};


3. My solution2(DP) 

利用solution1打印出前23个结果后我发现:

Num integerBreak(num)

2 1

3 2

4 4

5 6

6 9

7 12

8 18

9 27

10 36

11 54

12 81

13 108

14 162

15 243

16 324

17 486

18 729

19 972

20 1458

21 2187

22 2916

23 4374

 

得到的结果必然是多个3和2的乘积。

 

于是我想到这样的状态转移方程:dp[i]=max(dp[i-3]*3,dp[i-2]*2)

 

当然num<=6时,我们不可以用这种方法求解,因为此时num本身可以被分解成单个或两个2与3的乘积。

1和2比较特殊,他们只能分解成1.

而3只能分解成2和1。

4=2+2

5=2+3

6=3+3

因为我们至少要把这个数分解成2个数,但是4,5,6最多也就分解成两个“2或3”的和了,如果用之前的数组求解,还不如把他们自己得到的2和3求乘积的值大。

所以1~6我们都特殊判定一下,之后的数,至少都可以分解成3个“2或3”的和,用前面得到的dp值求解就可以了。

class Solution
{
private:
int dp[60];
public:
int integerBreak(int n)
{
dp[1]=1,dp[2]=1,dp[3]=2,dp[4]=4,dp[5]=6,dp[6]=9;
for(int i=7;i<=n;i++)
dp[i]=max(dp[i-3]*3,dp[i-2]*2);
return dp
;
}
};
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息