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