从最接近目标值的数组中选择值的算法?

时间:2010-06-28 16:35:46

标签: c algorithm math embedded

我有一个几乎排序值的数组,长28个元素。我需要找到与算法提供的目标值相加的一组值(或者如果找不到精确的和,则最接近的总和 目标值)。

我目前有一个简单的算法来完成这项工作,但并不总能找到最佳匹配。它在理想情况下使用一组特定的值,但我需要一个更强大,更准确的解决方案,可以处理更多种类的数据集。

算法必须用C语言编写,而不是用C ++编写,并且用于嵌入式系统,因此请记住这一点。

这是我目前的算法供参考。它从可用的最高值开始迭代。如果当前值小于目标总和,则将该值添加到输出并从目标总和中减去该值。重复此过程直到达到总和或用完值。它提出了一个几乎提升的排序列表。

//valuesOut will hold a bitmask of the values to be used (LSB representing array index 0, next bit index 1, etc)

void pickValues(long setTo, long* valuesOut)
{
    signed char i = 27;//last index in array
    long mask = 0x00000001;

    (*valuesOut) = 0x00000000;
    mask = mask<< i;//shift to ith bit
    while(i>=0 && setTo > 0)//while more values needed and available
    {
        if(VALUES_ARRAY[i] <= setTo)
        {
            (*valuesOut)|= mask;//set ith bit
            setTo = setTo - VALUES_ARRAY[i]._dword; //remove from remaining         }
        //decrement and iterate
        mask = mask >> 1;
        i--;
    }
}

还有一些参数:

  • 值数组可能近似排序升序,但无法强制执行,因此假设没有排序。实际上,也可能存在重复值。

  • 数组很可能包含一组不能在其范围内创建每个总和的值。如果无法找到确切的总和,则算法应返回创建下一个最低总和的值。

3 个答案:

答案 0 :(得分:7)

此问题称为子集求和问题,这是Knapsack problem的特例。维基百科是一些算法的良好起点。

答案 1 :(得分:6)

正如其他人所说,这与子集和问题的优化版本相同,即NP-Complete。

由于您提到内存不足并且可能使用近似解(基于您当前的解决方案),因此有多项式时间近似算法可用于求解子集和的优化版本。

例如,给定e> 0,有一个多项式时间算法,它使用O((n * logt)/ e)空间,(t是目标和,n是数组的大小),它给你一个子集,使得和z不小于比最优的1 /(1 + e)倍。

即如果最大子集和为y,则算法找到子集sum z,使得

z <= y <= (1+e)z

并使用空格O((n * logt)/ e)。

可在此处找到此类算法:http://www.cs.dartmouth.edu/~ac/Teach/CS105-Winter05/Notes/nanda-scribe-3.pdf

希望这有帮助。

答案 2 :(得分:1)

如果值相当小,则它是一个简单的动态编程(DP)。时间复杂度将是O(n *目标)和存储器要求O(目标)。如果这满足你,网上有很多DP教程。例如,这里讨论的第一个问题(使用couns)与您的问题非常相似(除了它们允许多次使用每个数字):
http://www.topcoder.com/tc?module=Static&d1=tutorials&d2=dynProg

<强>更新 是的,正如其他人所说,这是一个背包问题的简单案例。