被这个题折磨了好久好久……得有两三天吧,太丢人了
知道使用dp的思路来做,但是第一次dp的思路错误了,认为在每一个规模为a的问题中差的绝对值最小时,沿着这条路线,再继续选择在当前差值上增加的值最小的元素就可以了。
比如:
4 2
5 4
5 4
9 0
0 9
这个集合,明显应该选后两个,但是沿着刚才的思路的话,选择的结果是前两个。
这也证明了局部最优不等于全局最优。
在知道思路错了之后,看了别人的解题报告,了解了正确的想法,但是看得不够仔细,自己写的时候出现了很多很多错误……
正确思路是:
用两个数组dp[i][j]和path[i][j],i表示正在选的是第几个元素,j表示选了i个元素后的差的绝对值(用的是枚举的办法,记录下每次选一个元素后每个可能的值),dp的值是使取得j的时候的当前和值(包括前面选的元素的和值),path保存的是当前选的这个元素的下标。计算的时候,要保证 本次选的元素以前没有被选 以及 如果有多个元素可以使j取某一值,选择和值最大的那个。
因为差值可能去负数,所以在计算时在j值上加上了一个常数,防止数组越界。
算完了这两个数组后,可以找到选择了最后一个元素后,j最小而且dp[][j]最大的那个元素,然后沿着path数组倒序查找就可以找到全部选择(有点类似Viterbi算法)。
1. 由于这个子问题划分的思路很别扭,写的时候总是思考的太慢,在写代码上就花了不少时间。
2. 涉及的数组多,在下标犯了几个错误,看来我还是不够细心……
3. 忘记了每轮计算结束后,重新初始化所需要的变量。
4. 在循环中,赋值与下标的关系要计算好,而且不要忘记给一些元素赋值,总之,写这些略复杂的逻辑的时候,一定要细心。写的时候多花几分钟,debug的时候可以省下几十分钟……