标签:剑指offer offer col 成长 item 递归 color 选择 约束
给你一根长度为n的绳子,请把绳子剪成整数长的m段(m、n都是整数,n>1并且m>1),每段绳子的长度记为k[1],...,k[m]。请问k[1]x...xk[m]可能的最大乘积是多少?例如,当绳子的长度是8时,我们把它剪成长度分别为2、3、3的三段,此时得到的最大乘积是18。
n(绳子长度)
答案
约束:k[1]+...+k[m] = n
目标:MAX(πk[m])
逐步确定绳子的每一段长度,暴力穷举递归得出答案。
// 确定第一段与其他段长度的乘积 public int fun(int n) { int con = 0; for (int i = n-1; i>=1; i--) { for (int j=n-i; j>=1; j--) { int item = func(n, i, j); con = Math.max(con, item); } } return con; } // 确定后续绳子长度 public int func(int n, int k, int max) { int con = 0; if (n - k - max < 2) { con = k * max; } else { for (int i = max; max>=1; max--) { if (i + max + k > n) continue; int item = k * func(n - k, max, i); con = Math.max(con, item); } } return con; }
光暴力就想了两个小时,果然菜是原罪,学习学习优化思想。
在对问题进行求解时,在每一步选择中都采取最好或者最优(即最有利)的选择,从而希望能够导致结果是最好或者最优的算法。
贪婪算法并没有固定的算法解决框架,算法的关键是贪婪策略的选择,根据不同的问题选择不同的策略。
必须注意的是策略的选择必须具备无后效性,即某个状态的选择不会影响到之前的状态,只与当前状态有关,所以对采用的贪婪的策略一定要仔细分析其是否满足无后效性。
思路:把绳长target剪成i段的最大值为:Math.pow(n, i - c) * Math.pow(n + 1, c),如:target=8 i=3时,ans=2^1*3^2然后在剪成2段、3段...x段中取最大值即可。
public int cutRope(int target) { int result = 0; for (int i = 2; i <= target; i++) { int n = target / i, c = target % i; int ans = (int) (Math.pow(n, i - c) * Math.pow(n + 1, c)); if (ans > result) { result = ans; } } return result; }
思路:整体可由局部和局部的最优解相乘得到,如果把长度n绳子的最大乘积记为f(n),则有:f(n)=max(f(i)*f(n-1))
,因此不断由小推导至大,最终求出n的结果。因此设置一个数组用来存放对应的最大乘积数。
public int cutRope(int target) { //当长度大于3 f[n]才能得到绳子的最大乘积因为target>1,m>1 if(target==2) return 1; if(target==3) return 2; int [] f = new int[target+1]; f[0] = 0; f[1] = 1; f[2] = 2; f[3] = 3; for (int i = 4; i <f.length ; i++) { int max = 0; //计算f(n)*f(n-i) for (int j = 1; j <=i/2 ; j++) { int temp = f[j]*f[i-j]; max = Math.max(temp,max); } f[i] = max; } return f[target]; }
标签:剑指offer offer col 成长 item 递归 color 选择 约束
原文地址:https://www.cnblogs.com/codejess/p/13169795.html