比如我有数组a[9]={10,20,30,40,50,60,70,80,90}
(这里的例子是递增的,但是不代表所有的样例都是递增或者递减的,样例是无规律的正数),然后划分成三个单独的数组,分两种情况,一种情况是保持原有顺序的划分,另外一种是可以乱序的划分,对于前者 如果把10 30划在一起,20必然也在一起。最后要得到一个结果使得各组数组中和的最大值最小,比如上面对于保持原有顺序的划分就是10,20,30,40,50|60,70|80,90 这个值就是170。问一下大家对于保持顺序和不保持顺序的两种划分方式的最优算法。
保序问题
保持顺序的划分问题先找个简单的例子。比如把数列1,2,3,4,5,6划分成3组,则最后一组可能有1-4个元素:
[12345]6
[1234]56
[123]456
[12]3456
然后在这4种划分中选一个最优的(如果有并列最优则任取一个)即可。中括号[]里面是一个更小规模的问题(把数列划分成两组)。由此可总结出一个递归算法。
给定数列
a[1], a[2], ... a[m]
,记A[i,j] = a[i], a[i+1], ... a[j]
。函数groups(A[1,m],n)
给出一个将数列划分成n
组的最优划分。例如:递归公式为:
其中“+”表示将右边的数列作为最后的分组附加到左边的分组结果上,
min
是选出最优分组的操作(最大分组和最小)。以下是Mathematica实现,缓存了中间结果(memoization)。
测试:
不保序问题
不保序的划分问题称为Multi-way partition problem,是NP-hard。 stackexchange上有个类似的问题和解答,参见这里。