uva 1045 - The Great Wall Game(二分图匹配)

来源:互联网 发布:淘宝商品资质要填吗 编辑:程序博客网 时间:2024/06/02 19:28

题目链接:uva 1045 - The Great Wall Game


枚举最终移动到的行和列,以及两条对角线,建立二分图,X集合为棋子,Y集合为目标位置,边权为棋子移动到目标位置的代价,做完美匹配,求最小值。


#include <cstdio>#include <cstring>#include <cstdlib>#include <vector>#include <algorithm>using namespace std;const int maxn = 20;const int inf = 0x3f3f3f3f;int N, L[maxn], Lx[maxn], Ly[maxn], slack[maxn];int X[maxn], Y[maxn], W[maxn][maxn];bool S[maxn], T[maxn];void setCol (int c) {for (int i = 1; i <= N; i++) {for (int j = 1; j <= N; j++)W[i][j] = -(abs(X[i]-j) + abs(Y[i]-c));}}void setRow (int r) {for (int i = 1; i <= N; i++) {for (int j = 1; j <= N; j++)W[i][j] = -(abs(X[i]-r) + abs(Y[i]-j));}}bool match (int u) {S[u] = true;for (int i = 1; i <= N; i++) {if (!T[i]) {if (Lx[u] + Ly[i] == W[u][i]) {T[i] = true;if (!L[i] || match(L[i])) {L[i] = u;return true;}} elseslack[i] = min(slack[i], Lx[u]+Ly[i]-W[u][i]);}}return false;}void update () {int a = inf;for (int i = 1; i <= N; i++) if (!T[i])a = min(a, slack[i]);for (int i = 1; i <= N; i++) if (S[i]) Lx[i] -= a;for (int i = 1; i <= N; i++) if (T[i]) Ly[i] += a;}int KM () {for (int i = 1; i <= N; i++) {Lx[i] = L[i] = Ly[i] = 0;for (int j = 1; j <= N; j++) Lx[i] = max(Lx[i], W[i][j]);}for (int i = 1; i <= N; i++) {for (int j = 1; j <= N; j++) slack[j] = inf;while (true) {for (int j = 1; j <= N; j++) S[j] = T[j] = false;if (match(i)) break;else update();}}int ret = 0;for (int i = 1; i <= N; i++)ret += (Lx[i] + Ly[i]);return -ret;}int solve () {int ans = inf;for (int i = 1; i <= N; i++) {setCol(i);ans = min(ans, KM());setRow(i);ans = min(ans, KM());}for (int i = 1; i <= N; i++) {for (int j = 1; j <= N; j++)W[i][j] = -(abs(X[i]-j) + abs(Y[i]-j));}ans = min(ans, KM());for (int i = 1; i <= N; i++) {for (int j = 1; j <= N; j++)W[i][j] = -(abs(X[i]-j) + abs(Y[i]- (N-j+1)));}ans = min(ans, KM());return ans;}int main () {int cas = 1;while (scanf("%d", &N) == 1 && N) {for (int i = 1; i <= N; i++) scanf("%d%d", &X[i], &Y[i]);int ans = solve();printf("Board %d: %d moves required.\n\n", cas++, ans);}return 0;}


0 0