weixin_42363604 2023-02-14 02:01 采纳率: 100%
浏览 36
已结题

一个任务平均分配算法问题

有ABCDE等多个区域经理,现在有区域一二三四等若干个区域的任务向区域经理分配,每个经理负责的区域不同,(例如A负责一二三,B负责二四 C负责三五六),并且每个区域经理手上已经可能存在一定量的任务,求一种算法思路使得尽可能的使每个经理手上最后分配到的任务数量相同。

示例:A=1 B=60 C=5 D=5 E=10 F=40(每个经理手中初始任务数量)

           区域一=20   区域二=15  区域三=10  区域四=10  区域五=0 (目前需要被分配的任务数量)

          A负责区域一二三四

          B负责区域一二三四

          C负责区域一三四

          D负责区域二

          E负责区域三

          F负责区域一四五

这个例子最后期望是A=19 B=60 C=19 D=19 E=19 F=40

我试过自己写贪心\动态规划 但都在个别极端情况下出现了分配不均或局部不均的情况,可不可以给个思路,有C++的或者其他的代码更好。

  • 写回答

3条回答 默认 最新

  • 量化研究所 2023-02-14 16:54
    关注

    这是一个NP-hard问题,通常需要采用启发式算法来求解。这里介绍一种贪心算法的思路,可能并不能保证达到最优解,但是可以得到一个比较好的近似解。

    首先,将所有任务按照区域编号升序排列。然后,对于每个经理,统计该经理已经负责的区域中的任务数量之和。对于每个任务,按照区域编号升序依次将其分配给还未负责该区域的任务数量最小的经理。如果存在多个经理任务数量相同时,选择任务数量之和最小的那个经理。最后,检查各个经理手上的任务数量,如果有经理比其他经理任务数量多出了两个或以上的任务,那么就从该经理手中数量最多的任务中选择一个,分配给任务数量最少的经理。

    下面是一个C++实现的代码示例(假设区域编号从1开始):

    
    ```c++
    #include <iostream>
    #include <vector>
    #include <algorithm>
    #include <map>
    
    using namespace std;
    
    // 定义经理和区域的类型
    typedef vector<int> Manager;
    typedef vector<int> Region;
    
    // 打印经理和区域的任务情况
    void print(const Manager& mgr, const Region& region) {
        for (int i = 0; i < mgr.size(); ++i) {
            cout << "Manager " << char('A' + i) << ":";
            for (int j = 0; j < region.size(); ++j) {
                if (mgr[i] == j) {
                    cout << " " << region[j];
                }
            }
            cout << endl;
        }
    }
    
    // 贪心分配任务
    void assign(const Manager& mgr, const Region& region, Manager& result) {
        // 统计每个经理已经负责的区域中的任务数量之和
        map<int, int> taskCount;
        for (int i = 0; i < mgr.size(); ++i) {
            taskCount[i] = 0;
            for (int j = 0; j < region.size(); ++j) {
                if (mgr[i] == j) {
                    taskCount[i] += region[j];
                }
            }
        }
    
        // 按照区域编号升序分配任务
        for (int i = 0; i < region.size(); ++i) {
            int minTaskCount = INT_MAX;
            vector<int> candidate;
            for (int j = 0; j < mgr.size(); ++j) {
                if (mgr[j] == i) continue;
                if (taskCount[j] < minTaskCount) {
                    candidate.clear();
                    candidate.push_back(j);
                    minTaskCount = taskCount[j];
                } else if (taskCount[j] == minTaskCount) {
                    candidate.push_back(j);
                }
            }
            if (candidate.size() == 1) {
                result[i] = candidate[0];
                taskCount[candidate[0]] += region[i];
            } else {
    
    int minSum = INT_MAX;
    int selected = -1;
    for (int j : candidate) {
        int sum = 0;
        for (int k = 0; k < m; k++) {
            sum += abs(data[k][j]);
        }
        if (sum < minSum) {
            minSum = sum;
            selected = j;
        }
    }
    
    
    
    

    这段代码中,首先初始化 minSum 为整型最大值,selected 为 -1,然后遍历候选的区域经理,计算每个区域经理当前任务量的绝对值之和,即上文代码中的 calculateSum() 函数返回值,将结果保存在 sum 变量中,如果 sum 小于当前最小值 minSum,则将 minSum 更新为 sum,同时将 selected 更新为当前区域经理 j。最后返回选中的区域经理的编号 selected。

    ```

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(2条)

报告相同问题?

问题事件

  • 系统已结题 2月28日
  • 已采纳回答 2月20日
  • 修改了问题 2月14日
  • 修改了问题 2月14日
  • 展开全部

悬赏问题

  • ¥15 matlab答疑 关于海上风电的爬坡事件检测
  • ¥88 python部署量化回测异常问题
  • ¥30 酬劳2w元求合作写文章
  • ¥15 在现有系统基础上增加功能
  • ¥15 远程桌面文档内容复制粘贴,格式会变化
  • ¥15 关于#java#的问题:找一份能快速看完mooc视频的代码
  • ¥15 这种微信登录授权 谁可以做啊
  • ¥15 请问我该如何添加自己的数据去运行蚁群算法代码
  • ¥20 用HslCommunication 连接欧姆龙 plc有时会连接失败。报异常为“未知错误”
  • ¥15 网络设备配置与管理这个该怎么弄