寻找子集组合以实现给定总和同时保持成本最小的算法

Posted

技术标签:

【中文标题】寻找子集组合以实现给定总和同时保持成本最小的算法【英文标题】:Algorithm for finding subset combination for achieving a given sum, while keeping the cost minimum 【发布时间】:2016-10-21 15:36:46 【问题描述】:

我有一个问题,我有一个具有以下结构的元素数组:

struct Band

    int index;
    int length;
    int cost;
;

现在,我需要选择一个或多个元素的组合,其中每个元素都有一个唯一的索引,即没有一个元素可以有相同的索引。这种元素组合的长度总和应该完全等于N,如果有多个这样的组合,那么我需要选择成本最低的一个。

有什么想法吗?我目前的解决方案不起作用,所以我不确定是否应该在这里分享。谢谢!

编辑:这就是我现在所拥有的。 selected 是所选元素的索引集,startI 是起始索引,ranageMax 是结束索引(全局)。 L 是要求的长度,M 是我们拥有的最大资金,所以成本必须小于它。

void knapsack(struct Band rubber[], int currLen, int cost, int startI, set<int> selected)

    if(startI == rangeMax)
    
        /*&root[startI].length = currLen;
        root[startI].cost = cost;*/
        cout << "\n";
        return;
    
    if(cost > M || currLen > L)
    
        cout<< "\n";
        return;
    
    if(currLen == L)
    
        //cout << "Candidate : " << cost << endl;
        cout << "\n";
        if(cost < minv)
            minv = cost;
        return;
    
    for(int i=startI; i<rangeMax; ++i)
    
        //knapsack(rubber, currLen, cost, startI+1, selected);
        if(selected.find(rubber[i].index) == selected.end())
        
            selected.insert(rubber[i].index);
            cout << rubber[i].length << " ";
            int tempCurrLen = currLen + rubber[i].length;
            int tempCost = cost + rubber[i].cost;
            /*root[i].length = currLen;
            root[i].cost = cost;*/
            knapsack(rubber, tempCurrLen, tempCost, i+1, selected);
            selected.erase(rubber[i].index);
        
    

【问题讨论】:

您目前的解决方案是什么? 在问题中添加了我的“解决方案”,请不要评判我:P 【参考方案1】:

在关于knapsack problem 的***文章中,描述了一种动态规划算法,该算法将权重 组合起来以最大化利润。为了解决原始问题中描述的问题,必须组合长度以优化成本。我们使用二维状态空间如下。

C[i,j] is defined as the minimum cost attainable for a selection of items
       with indices in 1,...,i of total length exactly j
       or positive infinity if there is no such selection

基于该定义,我们得到以下递归关系。

C[i,j] = min C[i-1,j-weight[i]] + cost[i], C[i-1,j] 

这个递归关系是正确的,因为最小值中的第一项对应于选择索引为i 的项目,而第二项对应于选择索引为i 的项目不 em> 进入解决方案。状态空间必须用正无穷大的值初始化,除了对应于单个项目的选择的状态。然后可以通过增加i 一个外部循环并遍历

中的所有可能值,以自下而上的方式评估状态
0,....,N

在一个内部循环中。经过评估,最低费用可以在C[n,N]找到。如果需要选择所需的项目,则必须使用回溯或辅助数据结构来生成它。

请注意,在上面的演示中,如果任何参数是正无穷大,我们假设值的相加是正无穷大。

【讨论】:

感谢您的回答!但是,这并没有考虑到 分组 问题,即特定索引只能有一个元素。另外,只是一个小建议,在递归关系中应该是 糟糕,不小心按了 Enter。所以我认为递归关系应该是:codeC[i,j] = min C[i-1,j-length[i]] + cost[i], C[i-1,j] @ 987654330@ 最低成本将在 C[L,N] 中找到。如果我错了,请纠正我!

以上是关于寻找子集组合以实现给定总和同时保持成本最小的算法的主要内容,如果未能解决你的问题,请参考以下文章

在总和匹配的两组整数中查找子集的算法

总和大于或等于 k ​​的最小子集

将给定的一组数字 N 分成两组,以使它们的总和之差最小?

回溯 - 给定一组数字,找到总和等于 M 的所有子集(给定 M)

如何更有效地从n组中找到满足给定条件的最小组合?

给定一个目标总和和一组整数,找到与该目标相加的最接近的数字子集