網格地圖包含 'm'(人)和 'H'(房子),每人分配一間不同房子,最小化總曼哈頓距離。人數 = 房數 ≤ 100。
cost = 300 - dist(轉為最大權匹配,KM 算法求最大權)人數*300 - maxWeightlx[i] = max_j w[i][j], ly[j] = 0lx[i]+ly[j]==w[i][j])中尋找增廣路δ = min_{x∈S, y∉T} (lx[x]+ly[y]-w[x][y]),更新 lx[x]-=δ, ly[y]+=δbool dfs(int u) {
vx[u] = true;
for (int v = 0; v < n; ++v) {
if (vy[v]) continue;
int gap = lx[u] + ly[v] - w[u][v];
if (gap == 0) {
vy[v] = true;
if (match[v] == -1 || dfs(match[v])) {
match[v] = u; return true;
}
} else slack[v] = min(slack[v], gap);
}
return false;
}
void km() {
fill(lx, lx+n, 0);
fill(ly, ly+n, 0);
fill(match, match+n, -1);
for (int i = 0; i < n; ++i)
for (int j = 0; j < n; ++j)
lx[i] = max(lx[i], w[i][j]);
for (int i = 0; i < n; ++i) {
fill(slack, slack+n, INF);
while (true) {
fill(vx, vx+n, false);
fill(vy, vy+n, false);
if (dfs(i)) break;
int d = INF;
for (int j = 0; j < n; ++j) if (!vy[j]) d = min(d, slack[j]);
for (int j = 0; j < n; ++j) {
if (vx[j]) lx[j] -= d;
if (vy[j]) ly[j] += d;
else slack[j] -= d;
}
}
}
}
|x1-x2| + |y1-y2|