动态规划与贪心算法_剪绳子问题
Posted cdlyy
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了动态规划与贪心算法_剪绳子问题相关的知识,希望对你有一定的参考价值。
问题:
给你一根长度为n绳子,请把绳子剪成m段(m、n都是整数,n>1并且m≥1)。每段的绳子的长度记为k[0]、k[1]、……、k[m]。k[0]*k[1]*…*k[m]可能的最大乘积是多少?例如当绳子的长度是8时,我们把它剪成长度分别为2、3、3的三段,此时得到最大的乘积18。
求解:
1.动态规划
求一个问题的最优解(最大值或最小值),而且该问题能够分解成若干子问题,并且子问题之间还有重叠的更小的子问题,可以考虑动态规划
(1) 分析是否能把大问题分解成小问题
(2) 分解后的每个小问题存在最优解
(3) 小问题的最优解组合起来能得到整个问题的最解
2.贪婪算法求解:
每一步都可以做出一个贪婪的选择,基于这个选择,确定能够得到最优解
1. 贪心算法在对问题求解时,不从整体最优上加以考虑,他所做出的是在某种意义上的局部最优解
2. 选择的贪心策略必须具备无后效性,即某个状态以前的过程不会影响以后的状态,只与当前状态有关
3. 题目贪心策略:当n>=5时,尽可能多地剪长度为3的绳子;当剩下的绳子长度为4时,把绳子剪成两段长度为2的绳子
1.首先用动态规划递归实现,动态规划实际上就是用空间效率换区时间效率的一种做法:
public class Test {
public static int getMax(int n){
//要求长度n>1,所以这里返回0表示输入非法
if(n<2){
return 0;
}
//长度为2时,要求剪下段数m>1,所以最大是1x1=1
if(n==2){
return 1;
}
//长度为3时,要求剪下段数m>1,所以最大是1x2=2
if(n==3) {
return 2;
}
//存储长度从 0-n 的最大结果
int[] result=new int[n+1];
result[0]=0;
result[1]=1;
result[2]=2;
result[3]=3;
//自底向上开始求解
int max=0;
for(int i=4;i<=n;i++){
//每次将最大乘积清空
max=0;
//因为要计算f(j)乘以f(i-j)的最大值,j超过i的一半时是重复计算,所以只需要考虑j不超过i的一半的情况
for(int j=1;j<=i/2;j++){
//计算f(j)乘以f(i-j)
int tempResult=result[j]*result[i-j];
if(max<tempResult) {
max = tempResult;
}
//更新表中的f(i)=max(f(j)·f(i-j))
result[i]=max;
}
}
max=result[n];
return max;
}
}
2.采用贪婪算法得到最优解:
public static int getMaxValue(int n){
if(n<2) {
return 0;
}
if(n==2) {
return 1;
}
if(n==3) {
return 2;
}
//先求出长度为3的段一共有多少段
int countOfThree=n/3;
//再看除了长度为3的段,还剩下多少米,如果还剩1米则表示有(n-1)个3和一个4,
// 所以要把上一步算出来的3的个数减1,把最后的4剪成两段长度为2的绳子
if(n-countOfThree*3==1){
countOfThree-=1;
}
//当剩下的绳子长度为4时,把绳子剪成两段长度为2的绳子
int countOfTwo=(n-countOfThree*3)/2;
//计算所有的3的countOfThree次方,再乘以剩下2的countOfTwo次方
return (int) ((Math.pow(3, countOfThree))*(Math.pow(2, countOfTwo)));
}
以上是关于动态规划与贪心算法_剪绳子问题的主要内容,如果未能解决你的问题,请参考以下文章