1.考点
- 考点1:动态规划:核心思想为“从上到下分析问题,从下往上解决问题”,另外的三个特性为:① 求一个问题的最优解(最大值/最小值);② 整体最优解 = 各个子问题的最优解相加; ③ 小问题之间有共同的各个子小问题;这些是动态规划的特性,在分析问题时可以从这些角度来考虑,当然核心思想不仅仅只用在这些问题,可以用在很多相关问题里。(比如推导出了递推类公式:f(n) = max(f(i)*f(n-i)),其中0<i<n,然后从下往上地对问题进行解决)
- 考点2:贪心算法:说穿了就是不断地取局部最优解,无论是剪绳子还是背包问题之类的,在循环中不断地取当前最优的解,直到最后发现更好的解,或者达到了循环的限制完成,其根据不同的题目有不同的变化,还是要多看题。
2.代码
- 三种写法,第一种是动态规划,核心是理解f(2)与f(3)在作为主问题和子问题时的取值区别;第二种是参照书上的贪心算法写法,代码较为简洁;第三种是常规思路的贪心算法,在循环中不断选择当前的最优解(剪3),直到最后剪完或者到达4和2这两种特殊情况。
#include <iostream>
using namespace std;
int maxProductAfterCutting_solution1(int length)
{
if (length < 2)
return 0;
if (length == 2)
return 1;
if (length == 3)
return 2;
int* bestSubProblem = new int[length + 1];
bestSubProblem[0] = 0;
bestSubProblem[1] = 1;
bestSubProblem[2] = 2;
bestSubProblem[3] = 3;
int max = 0;
for (int i = 4; i <= length; i++)
{
max = 0;
for (int j = 1; j <= i >> 1; j++)
{
int submax = bestSubProblem[j] * bestSubProblem[i - j];
if (submax > max)
{
max = submax;
bestSubProblem[i] = max;
}
}
}
max = bestSubProblem[length];
delete[] bestSubProblem;
return max;
}
int maxProductAfterCutting_solution2(int length)
{
if (length < 2)
return 0;
if (length == 2)
return 1;
if (length == 3)
return 2;
if (length == 4)
return 4;
int cut_three = length / 3;
if (length - cut_three * 3 == 1)
cut_three--;
int cut_two = (length - 3 * cut_three) / 2;
return pow(3, cut_three)*pow(2, cut_two);
}
int maxProductAfterCutting_solution3(int length)
{
if (length < 2)
return 0;
if (length == 2)
return 1;
if (length == 3)
return 2;
if (length == 4)
return 4;
int cut_three = 0;
int cut_two = 0;
while (length)
{
if (length != 4 && length != 2)
{
length -= 3;
cut_three++;
}
else
{
cut_two = length / 2;
break;
}
}
return pow(3, cut_three)*pow(2, cut_two);
}