链接: 饥饿的奶牛.
第一步:排序
按照右端点为第一关键字,左端点为第二关键字排序。 第二步:预处理数组p
这里是关键了!众所周知,dp的各个子结构之间是不能有关联的。我们的dp是按照区间进行dp,所以对于每一个区间k,都要计算出p[k]=q,它满足:
①0≤q<k
②选择区间k之后,区间1,2,3…q仍然可以选择
③选择区间k之后,区间q+1,q+2…k-1不能选择
我们只需要快速找到一个区间,使得该区间的右端点在k的左端点左边即可。
这样就可以在dp时,快速查询在执行“选”的决策时转移的区间。
另外这一步有一个细节:n的规模大,在寻找区间时需要二分而不能暴力寻找,否则会T掉第三个点。 第三步:dp
方程是非常简单的(前面的步骤全部都是为了dp)。每个区间只有两种决策(即选与不选)。
设dp[k]为只考虑前k个区间时最多能选到多少个点。如果选k,转移到dp[p[k]]+right[k]-left[k]+1;如果不选k,转移到dp[k-1]。
首先这个代码不是我写的,我写了将近一个多小时还是没有一个很好的方法能通过测试。最后还是看了网上的解题思路。虽然没写出来,好好总结一样的有收获。
binarysearch()函数:作用是,在区间0到q之间找到最大的一个j使得end[j]<sta[i],用到二分的思想,大大降低了时间复杂度。
代码的难点在我看来不在二分,首先是要想到用动态规划,其实我感觉对于动态规划学的比较好的人来说,一个不难看出来。但是对于我这种小菜鸡,还真没看出来。。。所以到了动态规划的章节要好好看看。
最后就是在我心里的重头戏了,怎么样按照右端点为第一关键字,左端点为第二关键字排序。反正我是不敢想的,能力限制了我的想象。。。。下面就来好好的解释一下别人是怎么操作的。
首先是两个函数comp1和comp2。comp1:相当于是判断小于。comp2:相当于是判断大于。这个我硬看了半天没看明白,后来自己随便举了一个栗子,手动运行了一下就明白了。。。这也算是领悟到了一个看代码的方法。
然后是sort函数,其实它就是一个就是一个快速排序。标兵是最中间的那个元素。然后comp1是小于号,comp2是大于号。这样一看就很好理解了。
这个串代码可谓是结合了动态规划,二分,快速排序为一体,怪不得我写到自闭。。。。
好了,还准备一天更完所有题目的,看样子今天只能更一题了。今天有事耽误了一早上时间。小菜鸡六级还没过,要去学学六级了。