题目描述
Farmer John的N(1<=N<=1000)头奶牛分别居住在农场所拥有的B(1<=B<=20)个牛棚的某一个里。有些奶牛很喜欢她们当前住的牛棚,而另一些则讨厌再在它们现在所在的牛棚呆下去。
FJ在忍受了若干次奶牛的抱怨后,决定为所有奶牛重新安排牛棚,使最不满的那头奶牛与最高兴的奶牛的心情差异最小,即使这会让所有奶牛都更加郁闷。
每头奶牛都把她对各个牛棚的好感度从高到低排序后告诉了FJ。当然,如果一头奶牛被安排到的牛棚在她给出的列表中越靠后,她就会越郁闷。你可以认为奶牛的郁闷指数是她被分配到的牛棚在列表中的位置。奶牛们是斤斤计较的,她们无法容忍别的奶牛在自己喜欢的牛棚里快乐地生活,而自己却呆在一个自己不喜欢的牛棚里。每个牛棚都只能容纳一定数量的奶牛。FJ希望在每个牛棚都没有超出容量限制的前提下,使最郁闷和最高兴的奶牛的郁闷指数的跨度最小。
FJ请你帮他写个程序,来计算这个最小的郁闷指数跨度到底是多少。
思路
我们可以枚举一个放的区间,将每一个牛棚拆为若干个点,用匹配判断当前的方案是否可行
#include <stdio.h> #include <string> #include <cstring> using namespace std; #define fill(x, y) memset(x, y, sizeof(x)) #define max(x, y) ((x) > (y) ? (x) : (y)) int l, r, n, m; int tot[31], a[1001][31], p[31][1001], ans; bool fl[31]; int tarjan(int now) { for (int i = l; i <= r; i++) { int t = a[now][i]; if (p[t][0] < tot[t]) { p[t][0]++; p[t][p[t][0]] = now; return 1; } else if (!fl[t]) { fl[t] = 1; for (int j = 1; j <= p[t][0]; j++) { if (tarjan(p[t][j])) { p[t][j] = now; return 1; } } } } return 0; } int work() { ans = 0x7f7f7f7f; for (l = 1; l <= m; l++) { fill(p, 0); r = l; for (int i = 1; i <= n; i++) { while (1) { fill(fl, 0); if (tarjan(i)) break; r++; if (r > m) break; if (r - l + 1 >= ans) break; } if (r - l + 1 >= ans) break; } if (r <= m && r - l + 1 < ans) ans = r - l + 1; } } int main() { scanf("%d%d", &n, &m); for (int i = 1; i <= n; i++) for (int j = 1; j <= m; j++) scanf("%d", &a[i][j]); for (int i = 1; i <= m; i++) scanf("%d", &tot[i]); work(); printf("%d\n", ans); }