题目:给你一段长度为n 的绳子,请把绳子剪成 m 段,每段长度记作 k1,k2,...km, 要求使得 k1 * k2 * ...km 乘积最大。
思路:动态规划满足的特点:
特点1:求一个问题的最优解,通常是求最大值或最小值问题。
特点2:该问题可以拆分为若干个子问题,该问题的最优解又依赖于子问题的最优解。比如剪长度为5的绳子,依赖的子问题就是长度为1 和 4 子问题,与长度为2 和 3 子问题相比较下的最优解。
特点3:把大问题拆分成若干个小问题,这些小问题之间彼此重复。比如求绳子为5的,与求绳子为6的,重叠子问题就在于,求5时已经算过 4 (1和4),算6时还要算4 (2和4)。
特点4:从上往下分析问题,从下网上求解问题。比如求解为5的绳子,就要去计算1 与4 ,2 与3 ,是由5 才去联想到去计算1 4,2 5,然而代码里面求解是先计算1,2,3,4,
贪心:
贪心算法的要点在于贪心策略,贪心算法的特点是,局部最优解一定能求得总体最优解。
比如这题贪心策略是尽可能多剪长度为3的绳子,即一个数分解成多个3,比分解成其它数要大。这个需要证明。
当 n >= 5时, 2(n-2) > n, 3(n-3) >n , 同时 , 3(n-3) >= 2(n-2)
注意! 当n ==4 时,2(n-2) > 3(n-3)
import java.util.Scanner;
public class CutShenzi {
public static void main(String[] args) {
System.out.println("绳子长度,N=");
Scanner in = new Scanner(System.in);
int n = in.nextInt();
System.out.println(Dynamic(n));
//System.out.println(Tanxin(n));
}
public static int Dynamic(int len) {
int max=0;
if(len < 2) return 0;
if(len == 2) return 1;
if(len == 3) return 2;
int [] arr = new int [len+1];
arr[0]=0;
arr[1]=1;
arr[2] = 2;
arr[3] = 3;
for(int i=4;i<=len;i++) {
for(int j=1;j<=i/2;j++) {
int tmp = arr[j] * arr[i-j];
if(max<tmp) max = tmp; //穷举找到乘积i最大值
}
arr[i] = max;
}
/*
for (int i = 0; i < arr.length; i++) {
System.out.print(arr[i]+" ");
}
System.out.println("=====================");
*/
return arr[len];
}
public static int Tanxin(int len) {
if(len < 2) return 0;
if(len == 2) return 1;
if(len == 3) return 2;
//贪心策略,多剪 长度为3的绳子
int timesof3 = len/3;
//当长度为4时,应该剪成2*2 > 1*3
if(timesof3*3+1==len) timesof3--;
int timesof2 = (len-timesof3*3)/2;
return (int)Math.pow(3, timesof3) * (int ) Math.pow(2, timesof2);
}
}
总结:这个题其实就是求一个数分解成若干个数k1,k2,km,,k1+k2+..km = n,并且求这几个k1,k2 ..km 乘积最大的题。
同时要记得动态规划与贪心的区别,动态规划的特点。