Algorithm 最大K子数组和

Algorithm 最大K子数组和,algorithm,sum,dynamic-programming,max,arrays,Algorithm,Sum,Dynamic Programming,Max,Arrays,我在处理这个问题的记忆和自下而上的方法算法时遇到了问题: 假设元素数组为“代码>席 >,< -> 10000 ,适用于所有 0 < i < n>代码>。试着找出T个元素的最大和,T(39)和(17)的最大和为16=9+7,K=2 T=4, 数组=39637=>(39633)最大和为18=9+6+3,K=1 *T=9,array=141816161218001189514=>连续子数组是(141118)(111218)(1118)K=3和max_sum=11+18+16+12+18+18=93*

我在处理这个问题的记忆和自下而上的方法算法时遇到了问题:

假设元素数组为“代码>席<代码> >,< <代码> -> 10000 <席〈10000 < /代码>,适用于所有<代码> 0 < i < n>代码>。试着找出T个元素的最大和,T 举例说明:

T=4,
数组=39117=>(39)和(17)的最大和为16=9+7,K=2

T=4,
数组=39637=>(39633)最大和为18=9+6+3,K=1

*T=9,array=141816161218001189514=>连续子数组是(141118)(111218)(1118)K=3和max_sum=11+18+16+12+18+18=93****对于T=15 array=619-29159-4527212-1052=>连续子数组是(619)(-29159)(527312)(-27210)(-22110)(-22123)K=5,最大和=19+15+9+27+3+12+27+10+11+23=156

这就是我到目前为止所做的:

设f[i][j][0]表示第一个i插槽和使用j插槽的最大和,不使用第i个插槽。

设f[i][j][1]表示第一个i插槽和使用j插槽的最大增益,使用第i个插槽。

显然,
f[i][j][k]
可以确定
f[i+1][j][k]
f[i+1][j+1][k]

详情:

    f[i+1][j+1][1]=max(f[i+1][j+1][1],f[i][j][0],f[i][j][1]+G[i+1]);
    f[i+1][j][0]=max(f[i+1][j][0],f[i][j][0],f[i][j][1]);

这是哈斯克尔的一个版本。函数“partitions”是由Daniel Fischer编写的,它以所有可能的方式对列表(或数组)进行分区。代码的其余部分测试长度大于1的元素(其组合长度与T匹配)的分区,并返回总和最大的一个(根据请求求和而不求第一个数)

导入数据列表(maximumBy)
导入数据。Ord(比较)
分区[]=[[]]
分区(x:xs)=[[x]:p | p过滤器(\y->length y>1)x)
$xs
结果=最大值(比较snd)
(zip toTest(map(\x->sum$map(sum.drop 1)x)toTest))
在putStrLn(
显示结果
++“K=”
++显示(长度$fst结果))
输出:
*Main>findMax 4[3,9,1,1,7]
([[3,9],[1,7]],16)K=2
*Main>findMax 4[3,9,6,3,7]
([[3,9,6,3]],18)K=1
*Main>findMax 9[14,11,18,1,1,16,12,18,0,0,11,18,9,5,14]
([[14,11,18],[1,16,12,18],[11,18]],93)K=3

示例不清楚:为什么不
T=4,array=39117=>(39117)最大和18=9+1+1+7,K=1
?很抱歉,我没有提到,我们必须在不同的子数组中查看t个元素,使它们的和最大,并且每个子数组的第一个元素不与其他元素求和。因此,在示例t=4,array=3 9 1 7中,我们必须查看4个元素,最好的解决方案是**(3 9)和(1 7)**因为7+9=16和每个子数组的第一个元素(3和1)并不重要。在任何其他情况下,我们都得到了一个较小的和。我希望这能清楚地表明:)也许“连续子序列/子列表”或至少“连续子数组”是一个更好的词?3,9,1,7也是一个“子数组”对于3,9,1,1,7和has sum=17,可能会添加一些示例,因为问题有点难以理解。我将添加更多示例:*T=9,array=14 11 18 1 16 18 0 11 19 5 14=>连续子数组是(14 11 18)(1 16 12 18)(11 18)K=3,max_sum=11+18+16+12+18+18=93****对于T=15数组=6 19-29 15 9-4 5 27 3 12-10 5-2 27 10-2 11 23-4 5=>相邻的子数组是(6 19)(-29 15 9)(5 27 3 12)(-2 27 10)(-2 11 23)由于K=5和max_sum=19+15+9+27+3+12+27+10+11+23=156非常感谢你们,我不清楚一件事:它不是很复杂吗?…当输入数组的长度约为10000时,生成所有可能的子集不需要太多时间?我试图用两个矩阵的动态规划来解决它,我在rec遇到了问题从矩阵构造解:)@user2177314是的,非常复杂。以您的长度为20且T=15的数组为例,代码已经花费了大约半分钟。一个更优化的解决方案肯定适合于长数组。这是一个相当具有挑战性的问题。我怀疑在不进一步研究的情况下,我是否会有一个解决方案。T谢谢你的介绍。我已经弄明白了!谢谢你是哈斯克尔implementation@user2177314太好了。你能发布你的答案吗?是的,我很快会发布一个详细的答案,现在我在协议:D的作业上遇到了一些问题
import Data.List (maximumBy)
import Data.Ord (comparing)

partitions [] = [[]]
partitions (x:xs) = [[x]:p | p <- partitions xs]
                 ++ [(x:ys):yss | (ys:yss) <- partitions xs]

findMax t xs = 
  let toTest = filter (\z -> (sum $ map length z) == t) 
               $ map (\x -> filter (\y -> length y > 1) x) 
               $ partitions xs
      result = maximumBy (comparing snd) 
               (zip toTest (map (\x -> sum $ map (sum . drop 1) x) toTest))
  in putStrLn( 
       show result 
       ++ " K = " 
       ++ show (length $ fst result))


OUTPUT:
*Main> findMax 4 [3,9,1,1,7]
([[3,9],[1,7]],16) K = 2

*Main> findMax 4 [3,9,6,3,7]
([[3,9,6,3]],18) K = 1

*Main> findMax 9 [14,11,18,1,1,16,12,18,0,0,11,18,9,5,14]
([[14,11,18],[1,16,12,18],[11,18]],93) K = 3