例题一
解法(贪⼼):
贪⼼策略:
我们的任何选择,应该让这个数尽可能快的变成
1
。
对于偶数:只能执⾏除
2
操作,没有什么分析的;
对于奇数:
i.
当
n== 1
的时候,不⽤执⾏任何操作;
ii.
当
n == 3
的时候,变成
1
的最优操作数是
2
;
iii.
当 (n / 2) % 2 == 0
的时候,那么它的⼆进制表⽰是 ......01
,最优的⽅式应该选择 -1
,这样就可以把末尾的
1
⼲掉,接下来执⾏除法操作,能够更快的变成 1 ;
iv.
当 (n / 2) % 2 == 1
的时候,那么它的⼆进制表⽰是 ......11
,此时最优的策略应该是 +1
,这样可以把⼀堆连续的
1
转换成
0
,更快的变成
1
。

例题二
解法⼀(动态规划):
将数组按照左端点排序之后,问题就转化成了最⻓上升⼦序列模型,那接下来我们就可以⽤解决最⻓上升⼦序列的经验,来解决这个问题。
1.
状态表⽰:
dp[i]
表⽰:以
i
位置的箱子为结尾的堆起来的箱子序列中,最高的箱子序列的高度;
2.
状态转移⽅程:
dp[i] = max(dp[i] , dp[j] + box[i] )
其中 0 <= j < i && box[i][0] > box[j][0] && box[i][1] > box[j][1]&& box[i][2] > box[j][2] ;
3.
初始化:
初始化为 每个箱子原来的高度
;
4.
填表顺序:
从左往右;
5.
返回值:
整个
dp
表中的最⼤值。

例题三
解法⼀(动态规划):
将数组按照左端点排序之后,问题就转化成了最⻓上升⼦序列模型,那接下来我们就可以⽤解决最⻓上升⼦序列的经验,来解决这个问题(虽然会超时,但是还是要好好写代码)。
1.
状态表⽰:
dp[i]
表⽰:以
i
位置的信封为结尾的所有套娃序列中,最⻓的套娃序列的⻓度;
2.
状态转移⽅程:
dp[i] = max(dp[j] + 1)
其中
0 <= j < i && e[i][0] > e[j][0] && e[i][1] > e[j][1] ;
3.
初始化:
全部初始化为
1
;
4.
填表顺序:
从左往右;
5.
返回值:
整个
dp
表中的最⼤值。
解法⼆(重写排序 + 贪⼼ + ⼆分):
当我们把整个信封按照「下⾯的规则」排序之后:
i.
左端点不同的时候:按照「左端点从⼩到⼤」排序;
ii.
左端点相同的时候:按照「右端点从⼤到⼩」排序;
我们发现,问题就变成了仅考虑信封的「右端点」,完完全全的变成的「最⻓上升⼦序列」的模型。那么我们就可以⽤「贪⼼ + ⼆分」优化我们的算法。
例题四
解法⼀(动态规划):
1.
状态表⽰:
dp[0][i]:表示取到第 i 个数的时候%3余数为0的最大值;
dp[1][i]:表示取到第 i 个数的时候%3余数为1的最大值;
dp[2][i]:表示取到第 i 个数的时候%3余数为2的最大值。
2.
状态转移⽅程:
1.当nums[i-1] % 3 == 0时
dp[0][i] = max(dp[0][i - 1], dp[0][i - 1] + nums[i - 1]);
dp[1][i] = max(dp[1][i - 1], dp[1][i - 1] + nums[i - 1]);
dp[1][i] = max(dp[1][i - 1], dp[1][i - 1] + nums[i - 1]);
dp[2][i] = max(dp[2][i - 1], dp[2][i - 1] + nums[i - 1]);
2.当nums[i - 1] % 3 == 1时
dp[0][i] = max(dp[0][i - 1], dp[2][i - 1] + nums[i - 1]);
dp[1][i] = max(dp[1][i - 1], dp[0][i - 1] + nums[i - 1]);
dp[2][i] = max(dp[2][i - 1], dp[1][i - 1] + nums[i - 1]);
3.当nums[i - 1] % 3 == 2时
dp[0][i] = max(dp[0][i - 1], dp[1][i - 1] + nums[i - 1]);
dp[1][i] = max(dp[1][i - 1], dp[2][i - 1] + nums[i - 1]);
dp[2][i] = max(dp[2][i - 1], dp[0][i - 1] + nums[i - 1]);
3.
初始化:
dp[0][0] = 0, dp[1][0] = INT_MIN, dp[2][0] = INT_MIN;
4.
填表顺序:
从左往右;
5.
返回值:
dp[ 0 ][ n ]
。

解法二(正难则反 + 贪⼼ + 分类讨论):
正难则反:
我们可以先把所有的数累加在⼀起,然后根据累加和的结果,贪⼼的删除⼀些数。
分类讨论:
设累加和为
sum
,⽤
x
标记
%3 == 1
的数,⽤
y
标记
% 3 == 2
的数。那么根据 sum
的余数,可以分为下⾯三种情况:
a.
sum % 3 == 0
,此时所有元素的和就是满⾜要求的,那么我们⼀个也不⽤删除;
b.
sum % 3 == 1
,此时数组中要么存在⼀个
x
,要么存在两个
y
。因为我们要的是最⼤值,所以应该选择 x
中最⼩的那么数,记为
x1
,或者是
y
中最⼩以及次⼩的两个数,记为y1,y2
。 那么,我们应该选择两种情况下的最⼤值: max(sum - x1, sum - y1 - y2)
;
c.
sum % 3 == 2
,此时数组中要么存在⼀个
y
,要么存在两个
x
。因为我们要的是最⼤值,所以应该选择 y
中最⼩的那么数,记为
y1
,或者是
x
中最⼩以及次⼩的两个数,记为 x1, x2
。
那么,我们应该选择两种情况下的最⼤值: max(sum - y1, sum - x1 - x2)
;

例题五
解法(贪⼼):
贪⼼策略:
每次处理⼀批相同的数字,往 n 个空⾥⾯摆放;每次摆放的时候,隔⼀个格⼦摆放⼀个数;优先处理出现次数最多的那个数。

例题六
解法(贪⼼):
贪⼼策略:
与上⾯的⼀道题解法⼀致~
