class Solution {
public:
int minDistance(vector<int>& houses, int k) {
const int n = houses.size();
vector<vector<int>> mem(n, vector<int>(k + 1, INT_MAX));
// cost[i][j] := the minimum cost to allocate mailboxes between houses[i]
// and houses[j]
vector<vector<int>> cost(n, vector<int>(n));
ranges::sort(houses);
for (int i = 0; i < n; ++i)
for (int j = i + 1; j < n; ++j) {
const int median = houses[(i + j) / 2];
for (int x = i; x <= j; ++x)
cost[i][j] += abs(houses[x] - median);
}
return minDistance(houses, 0, k, cost, mem);
}
private:
static constexpr int kMax = 1'000'000;
// Returns the minimum distance to allocate k mailboxes for houses[i..n).
int minDistance(const vector<int>& houses, int i, int k,
const vector<vector<int>>& cost, vector<vector<int>>& mem) {
if (i == houses.size() && k == 0)
return 0;
if (i == houses.size() || k == 0)
return kMax;
if (mem[i][k] != INT_MAX)
return mem[i][k];
for (int j = i; j < houses.size(); ++j)
mem[i][k] = min(
mem[i][k], cost[i][j] + minDistance(houses, j + 1, k - 1, cost, mem));
return mem[i][k];
}
};