Problem:
把一根绳子剪成多段,并且使得每段的长度乘积最大。
Intuition:
这一题比较容易,算是动态规划的开胃菜。首先我们聊一聊什么样的问题适合用动态规划。动态规划通常适合于要求我们求一个问题的最优解(通常是最大值或者最小值),而且该问题能够分解成若干个字问题,并且子问题之间还有重叠的更小的子问题,就可以考虑用动态规划来解决这个问题。下面的解法我们自己实现的方案既用了贪心算法的思想,也用了动态规划的思想。我们发现仅仅由dp[i-2],dp[i-3]就可以决定dp[i]里面的内容,原因是dp[i-p](p>3)里面的内容一定是可以由dp[i-2]和dp[i-3]来表示的。举个简单的例子,如果最优解是要用到dp[i-4],那么接下里剩下的4肯定是切成22,那么这种情况就与dp[i-2]2的情况是完全一致的。如果是dp[i-5],那么剩下对于5的切法一定是23,这个和dp[i-2]3或者dp[i-3]*2就是一致的。依次类推,这时属于贪心算法的内容。接下来就用动态规划来存之前计算的结果就可以了。
Solution:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54
| public int cutRope(int length){ int[] dp=new int[length+1]; dp[0]=0; dp[1]=1; dp[2]=2; dp[3]=3; if (length <= 3) { return dp[length]; } for(int i=4;i<=length;i++){ dp[i]=Math.max(dp[i-2]*2,dp[i-3]*3); } return dp[length]; }
public int cutRope_D(int length) {
if (length < 2) { return 0; } if (length == 2) { return 1; } if (length == 3) { return 2; } int[] products = new int[length + 1]; products[0] = 0; products[1] = 1; products[2] = 2; products[3] = 3;
int max = 0;
for (int i = 4; i <= length; i++) { max = 0; for (int j = 1; j <= i / 2; j++) { int product = products[j] * products[i - j]; if (product > max) { max = product; } products[i] = max; } } max = products[length];
return max; }
|