首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> C++ >> C++ 入門

HDU 2850 Load Balancing:貪心策略與優先隊列實現任務分配

     編輯:C++ 入門

題目大意

有 M 台伺服器,N 個任務,每個任務耗時 T_i。將任務分配給伺服器,使最大負載與最小負載之差最小化。輸出每個任務分配到的伺服器編號(0-based)。

貪心策略證明

此問題為 NP-hard 的多路數字分割問題,但題目為 SPJ(Special Judge),接受任意合法解。經典貪心策略:

  1. 任務按耗時 降序排列。
  2. 依序將任務分配給 當前總負載最小 的伺服器。

直觀理解:大任務優先放置,避免最後剩大任務無法平衡;每次選最閒伺服器,趨向負載均衡。

優先隊列優化

每次尋找最小負載伺服器若線性掃描 O(M),總複雜度 O(NM)。用最小堆(優先隊列)維護 (load, server_id),每次取出、更新、放回 O(log M),總複雜度 O(N log M)。

完整代碼

#include <cstdio>
#include <algorithm>
#include <queue>
#include <vector>
using namespace std;

struct Task { int time, idx, server; };
struct Server { int load, id; 
    bool operator<(const Server& other) const { return load > other.load; } // 最小堆
};

int main() {
    int T; scanf("%d", &T);
    while (T--) {
        int N, M; scanf("%d%d", &N, &M);
        vector<Task> tasks(N);
        for (int i = 0; i < N; ++i) {
            scanf("%d", &tasks[i].time);
            tasks[i].idx = i;
        }
        sort(tasks.begin(), tasks.end(), [](const Task& a, const Task& b) {
            return a.time > b.time;  // 降序
        });
        
        priority_queue<Server> pq;
        for (int i = 0; i < M; ++i) pq.push({0, i});
        
        for (int i = 0; i < N; ++i) {
            Server s = pq.top(); pq.pop();
            s.load += tasks[i].time;
            tasks[i].server = s.id;
            pq.push(s);
        }
        
        sort(tasks.begin(), tasks.end(), [](const Task& a, const Task& b) {
            return a.idx < b.idx;  // 恢復原順序
        });
        
        printf("%d\n", N);
        for (int i = 0; i < N; ++i) {
            if (i) putchar(' ');
            printf("%d", tasks[i].server);
        }
        puts("");
    }
    return 0;
}

反例說明

貪心非最優。例:N=6, M=2,任務 7 5 3 3 3 3。
貪心分配:
Server 0: 7+3+3 = 13
Server 1: 5+3+3 = 11
差值 2。
最優分配:
Server 0: 7+5 = 12
Server 1: 3+3+3+3 = 12
差值 0。
但 SPJ 僅檢查輸出格式合法性,不要求最優,故貪心可 AC。

複雜度分析

  • 排序:O(N log N)。
  • 堆操作:N 次 pop/push,每次 O(log M),共 O(N log M)。
  • 總時間:O(N log N + N log M),N ≤ 100,000, M ≤ 100 极快。
  • 空間:O(N + M)。

實作細節

  1. Server 重載 operator< 實現最小堆(priority_queue 預設為最大堆)。
  2. 任務結構體保存原始索引 idx,分配完成後按 idx 排序輸出。
  3. 多測資循環,每輪清空隊列重新初始化。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved