剪绳子
题目描述
给你一根长度为n的绳子,请把绳子剪成整数长的m段(m、n都是整数,n>1并且m>1),每段绳子的长度记为k[1],...,k[m]。请问k[1]x...xk[m]可能的最大乘积是多少?例如,当绳子的长度是8时,我们把它剪成长度分别为2、3、3的三段,此时得到的最大乘积是18。
输入描述:
输入一个数n,意义见题面。(2 <= n <= 60)
输出描述:
输出答案。
示例1
输出
复制18
法1:暴力递归破解法:
1 import java.io.BufferedReader; 2 import java.io.IOException; 3 import java.io.InputStreamReader; 4 5 6 public class test { 7 private static int back_track(int target){ 8 if(target<=4) return target; 9 10 int ret=0; 11 for(int i=1;i<=target;i++){ 12 int t = back_track(target - i); 13 ret = i*t>ret?i*t:ret; 14 } 15 return ret; 16 } 17 18 private static int cutRope(int target){ 19 if(target==2) return 1; 20 else if(target==3) return 2; 21 return back_track(target); 22 } 23 public static void main(String[] args) throws IOException { 24 System.out.println("请输入绳子的长度:"); 25 BufferedReader br=new BufferedReader(new InputStreamReader(System.in)); 26 int n=Integer.parseInt(br.readLine()); 27 System.out.println(cutRope(n)); 28 } 29 }
时间复杂度为O(n!),空间复杂度为O(n);相当于根结点为back_track(n)的一棵树,叶子结点都是back_track(1),树的深度是n,第二层从左到右的子树复杂度分别为O((n-1)!),O((n-2)!),...,最外面还有一层循环,所以是O(n!);
法2:记忆递归法:
1 import java.io.BufferedReader; 2 import java.io.IOException; 3 import java.io.InputStreamReader; 4 5 6 public class test { 7 private static int back_track(int target,int[] mark){ 8 if(target<=4) return target; 9 if(mark[target]!=0) { 10 return mark[target]; 11 } 12 int ret=0; 13 for(int i=1;i<=target;i++){ 14 int t = back_track(target - i,mark); 15 ret = i*t>ret?i*t:ret; 16 } 17 return mark[target]=ret; 18 } 19 20 private static int cutRope(int target){ 21 if(target==2) return 1; 22 else if(target==3) return 2; 23 int[] mark=new int[target+1]; 24 return back_track(target,mark); 25 } 26 public static void main(String[] args) throws IOException { 27 System.out.println("请输入绳子的长度:"); 28 BufferedReader br=new BufferedReader(new InputStreamReader(System.in)); 29 int n=Integer.parseInt(br.readLine()); 30 System.out.println(cutRope(n)); 31 } 32 }
时间复杂度是O(n^2),空间复杂度是O(n);最外面循环一遍,然后每个mark[i]计算一次,共计算n次,所以O(n^2);
法3:动态规划求解:
1 import java.io.BufferedReader; 2 import java.io.IOException; 3 import java.io.InputStreamReader; 4 5 public class pass { 6 private static int cutRope(int target){ 7 if(target==2) return 1; 8 else if(target==3) return 2; 9 int[] f=new int[target+1]; 10 for(int i=1;i<=4;i++){ 11 f[i]=i; 12 } 13 for(int i=5;i<=target;i++){ 14 for(int j=1;j<i;j++){ 15 f[i]=f[i]>j*f[i-j]?f[i]:j*f[i-j]; 16 } 17 } 18 return f[target]; 19 } 20 public static void main(String[] args) throws IOException { 21 System.out.println("请输入绳子的长度:"); 22 BufferedReader br=new BufferedReader(new InputStreamReader(System.in)); 23 int n=Integer.parseInt(br.readLine()); 24 System.out.println(cutRope(n)); 25 } 26 }
时间复杂度是O(n^2),空间复杂度是O(n);