【问题标题】:How to achieve a good performing grouping algorithm along distance criterion in C++如何在 C++ 中沿距离标准实现性能良好的分组算法
【发布时间】:2022-08-19 19:07:19
【问题描述】:

介绍

再会,

我正在寻找一种可以执行以下操作的分组算法:

假设我有一个排序数字数组(没有多次出现)。例如,{0、2、5、6、7、10}。

我想从该数组中创建组,例如:

  1. 尽量减少组数,
  2. 每个组需要包含最多链接的数字n - 1\"bonds\"(例如,n = 3, 0 和 2 是邻居,但不是 0 和 3)。

    编辑

    换句话说,当我说邻居时,我应该说整数距离。例如,0 到 2 i 2 的距离(反之亦然)。 0 到 3 的距离为 3。您可以将问题想象为一组 1D 点,需要找到最少数量的中心,其中中心包含距离它为 n/2 的点。我希望这样更清楚。


    该示例可能有多个组,但条件 1 和 2 (n = 3) 的最佳值是 {{0, 2}, {5, 6, 7}, {10}}。 {{0}, {2, 5}, {6, 7}, {10}} 比最佳解决方案多一组。如果所有排序的数字都是连续的,那么理想的解决方案就会发生:

    nb_groups* = ceil(v.size() / n);
    

    此外,根据算法,可能有多种解决方案。


    我试过的

    目前,我要做的是:

    1. 计算相邻元素之间的距离数组,
    2. 检查从向量开头到结尾的休止符的相邻条件(参见下面的代码)。

      它似乎工作(对我来说),但我想知道两件事:

      1. 它真的适用于任何情况吗(可能没有测试所有情况?)?
      2. 如果是这样,我能否以某种方式优化我的实现(优于 in.size() - 1 次迭代和更少的内存消耗)?

        代码

        我正在考虑一个将向量分组的函数,以及最大距离。此函数将返回组的第一个元素的索引。

        #include <iostream>
        #include <vector>
        
        std::vector<int> groupe(const std::vector<int>& at, const int& n);
        
        int main() {
            // Example of input vector
            std::vector<int> in = {0, 2, 5, 6, 7, 10, 11, 22, 30, 50, 51};
            // Try to group with neighbouring distance of 3
            std::vector<int> res = groupe(in, 3);
            
        
            // Printing the result
            for(const int& a : res) {
                std::cout << a << \" \";
            }
            
        }
        
        std::vector<int> groupe(const std::vector<int>& at, const int& n) {
            std::vector<int> out;
            
            // Reste keeps tracks of a bigger neighbouring distance (in case we can look for another element to be in the group)
            int reste(0);
            size_t s = at.size() - 1;
            for(int i = 0; i < s; i++) {
                // Computing the distance between element i and i + 1
                int d = at[i + 1] - at[i];
                
                if(d >= n) {
                    if(reste == 0) {
                        out.push_back(i);
                    }
                    reste = 0;
                } else {
                    if(reste == 0) {
                        out.push_back(i);
                    }
                    reste += d;
                    if(reste >= n) {
                        reste = 0;
                    }
                }
                
            }
            
            if(reste == 0 || reste >= n) {
                out.push_back(s);
            }
            
            return out;
        }
        
        

        输出

        0 2 5 7 8 9
        

        笔记

        如果原始向量没有排序,我想我们可以先对其进行排序,然后再完成这一步(或者可能有另一种更有效的算法?)。


        我提前感谢您的时间和帮助。

  • 它不太清楚你对“债券”的意思。 \"(例如,n = 3, 0 和 2 是邻居,但不是 0 和 3)。\" 嗯?!? 3,0 和 2 是邻居,但 0 和 3 不是?为什么?
  • 抱歉,如果这不清楚。我的意思是从 0 到 2 的距离是 2 \"bonds\" (2 - 0)。而对于 0 和 3,这是 3 (3 - 0)。
  • 你有一个简单的贪心算法会失败的例子吗? seems to work ok。我找不到贪心算法不能提供最佳解决方案的例子。
  • @MarekR 现在不是,如果您能看到一个失败的案例,那是我的问题的一部分。好的,谢谢,那么我的第一个问题似乎得到了回答。您是否看到任何优化改进?

标签: c++ algorithm grouping


【解决方案1】:

如前所述,此解决方案有效。

【讨论】:

    猜你喜欢
    • 2011-11-07
    • 2021-07-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-06-23
    相关资源
    最近更新 更多