Assign jobs to machines minimising the makespan — the completion time of the busiest machine. NP-hard even for (it contains partition).

Greedy: list scheduling

Assign each job to the currently least-loaded machine.

long long makespan(vector<long long> jobs, int m) {
    priority_queue<long long, vector<long long>, greater<>> load;
    for (int i = 0; i < m; i++) load.push(0);
    for (long long p : jobs) {
        long long l = load.top(); load.pop();
        load.push(l + p);
    }
    long long best = 0;
    while (!load.empty()) { best = max(best, load.top()); load.pop(); }
    return best;
}

Approximation ratio: (Graham, 1966).

Proof sketch. Let be the optimal makespan and consider the machine finishing last, whose final job has length . Before that job started, that machine was the least loaded, so its load was at most the average . Also . Hence the makespan is at most ; a sharper accounting gives . ∎

LPT — sort longest first

Sorting jobs in decreasing order before list scheduling improves the ratio to

One line of extra code for a substantially better guarantee, and in practice it is usually within a few percent of optimal.

sort(jobs.rbegin(), jobs.rend());          // then run list scheduling

Exact methods

Method
bitmask DP over assigned jobs
, meet in the middle
, complete Karmarkar-Karp
small subset-sum DP with a bitset
moderatebinary search the makespan + a feasibility check
largerbranch and bound with LPT as the incumbent

Binary search + bin packing check

Binary search the makespan and ask “can all jobs fit into bins of capacity ?” — a bin-packing feasibility question, itself NP-hard but often answered quickly by a backtracking search with:

  • jobs sorted descending,
  • skipping equal-length jobs already tried in the current position,
  • placing each job only in the first empty bin among identical empty bins (symmetry breaking),
  • pruning when the remaining jobs cannot fit in the remaining capacity.

This handles - comfortably and is the usual contest approach.

Approximation schemes

A PTAS exists: round job sizes, handle the “large” jobs exactly by enumeration, and fill in the small ones greedily. -approximate in time for fixed and . Of theoretical interest — the constants are impractical.

ProblemNote
Bin packingfewest bins of fixed capacity; First-Fit-Decreasing is
Partition, decide if a perfect split exists — see Subset Sum
Multiway number partitioningthe same problem, phrased numerically
Scheduling on unrelated machinesjob takes on machine ; 2-approximation by LP rounding (Lenstra-Shmoys-Tardos)
Scheduling with precedenceGraham’s list scheduling is still
Online load balancinggreedy is -competitive; no online algorithm beats
Minimise the sum of completion timeseasy: SPT, or round-robin across machines

That last row is the useful contrast: minimising the maximum load is NP-hard, but minimising the total completion time is a simple greedy. As with lateness, swapping max for sum changes the difficulty entirely — in the opposite direction this time.

Bin packing heuristics

HeuristicRatio
Next Fit2
First Fit1.7
Best Fit1.7
First Fit Decreasing
Best Fit Decreasingsame

FFD is the practical default: sort descending, place each item in the first bin that fits.

See also: Karmarkar-Karp · Subset Sum · Approximation Algorithms