http://www.cppblog.com/jsn1993/archive/2010/05/21/116026.html 上有一个很不错的方法,但可惜最坏情况下区间数还是O(n)级别的(b[1], b[2], ..., b[i]分别为2^i,后面的都取7000, 则所有偶数都可以组合出来,奇数都不可组合出来),因此其动规还是O(N^3)级别的。如果分组优化,把每组的大小设为(sqrt(n*4+1)+1)/2,可以把最坏情况的复杂度降至O(n^2.5)。
后来看了官方题解,发现其方法非常巧妙,核心为以下函数:
Algorithm 1 generate((p1 , p2 , p3 , ..., pm ), S)
if m = 1 then
S is one of the desired structures
else
S1 = add(S, (p1 , p2 , ..., p m/2 ))
S2 = add(S, (p m/2 +1 , ..., pm ))
generate((p m/2+1 , ..., pm ), S1 )
generate((p1 , p2 , ..., p m/2 ), S2 )
end if
参数中S为已经获得的可组合出的数,p1..pm为要加入的包。该算法可在O(B * n * m log m)内运行完毕,并能获得S加上p的所有m-1个元素的子集所能得到的组合结果。
由于官方数据比较厚道,区间数很少,我想到在以上算法的基础上加上区间处理的优化,于是程序运行的效果非常好……