POJ2127
要求求最长公共上升子序列并输出方案。首先是n^3做法:f[i,j]表示a串匹配到第i位、b串匹配到第j位时的最长公共上升子序列。f[i,j]=f[i-1,j] or f[i-1,k]+1(a[i]与b[k]相同时)。然后考虑要优化到n^2,我们只需要每次在找f[i-1,k]时把复杂度转化为O(1)。我们用一个变量MAX记录i-1时到j为止最大的f[i-1,j],由于要求必须是上升序列,所以我们只当a[i]>b[j]时才去更新MAX。转移时用MAX+1去和f[i,j]比较即可。输出方案的话需要记录前驱数组pre,由于一维可能会导致错误的覆盖,所以应该用二维的pre数组。
POJ2785
四组数,从每组中挑出一个使其和为0,求有多少种方案。我们可以把一二组的数、三四组的数两两相加,分别得到n^2个数,然后枚举数用hash从另一组里面寻找对应数的数目。第二次使用指针,发现了很多值得注意的问题(注:本人使用的为pascal语言):
1.新建指针时需要手动把node^.next赋值成nil
2.如果hash时mod的数太小,可能导致new()过多,导致超时
3.tmp指针可以定义为全局变量以节省内存(new过程中的除外)
POJ3700
导弹拦截加强版,可以用上升下降两种序列进行拦截。如果应用贪心思想,的确理论上每次都会存在一个最优的序列,但是找到这个序列无法实现。而且由于n很小,我们采用搜索加剪枝解决。每个点有四种状态:接在上升序列中、接在下降序列中、作为新上升序列的头、作为新下降序列的头。总状态数为4^50,急需强力剪枝。
1.由《组合数学》中的结论可知,长度为n的序列的ans不会超过sqrt(n),使用迭代加深
2.对于当前需要拦截的x号导弹,能省则省,能接在上升序列的后面就不新建上升序列,能接在下降序列后面就不新建下降序列。这不会对后面造成更会的影响。
3.当要把一个需要拦截的导弹加入以前的序列时,如果把以前的序列都扫一遍,最坏复杂度为O(n)。我们可以用一个数组记录到当前为止所有序列的最后一个的高度,上升序列维护其为降序,下降序列维护其为升序。这样添加到序列中时只需从第一个开始扫,遇到合适的就更改,没有合适的就在最后填一个新的。由于更改的元素之前的都不可行,之后的一定会可行,所以更改之后依然具有原来的单调性。
POJ1137
由于房间个数很少,可以用二进制表示开关灯的状态,进行BFS。
Nescafe17
第一题教训的话,要仔细观察样例吧。第二题要注意的是double也是很费内存的,开数组的时候要注意。把数组开大一点固然好,但是不要超过最高位。
浙公网安备 33010602011771号