这是一个简单的游戏,在一个n*n的矩阵中,找n个数使得这n个数都在不同的行和列里并且要求这n个数中的最大值和最小值的差值最小。
Input 输入一个整数T表示T组数据。
对于每组数据第一行输入一个正整数n(1<=n<=100)表示矩阵的大小。
接着输入n行,每行n个数x(0<=x<=100)。
Output 对于每组数据输出一个数表示最小差值。 Sample Input
1 4 1 1 1 1 2 2 2 2 3 3 3 3 4 4 4 4Sample Output
3
觉得这个对于二分姿势有点重要啊。
有一发写的二分正好避过了n=1时的正确答案。
跑匈牙利的时候枚举上下界【二分出来的上下界】。
#include <bits/stdc++.h> #define ms(x) memset(x, 0, sizeof(x)) #define inf 0x3f3f3f3f #define mf(x) memset(x, inf, sizeof(x)) #define mf1(x) memset(x, -1, sizeof(x)) using namespace std; const int N = 101; const int M = 10103; int uN, vN; int a[N][N]; bool used[N]; int linker[N]; bool dfs(int u, int ll, int rr) { for(int v=1; v<=uN; v++) { if(a[u][v] >=ll && a[u][v]<=rr && !used[v]) { used[v] = true; if(linker[v] == -1 || dfs(linker[v], ll, rr)) { linker[v] = u; return true; } } } return false; } bool hungry(int mid, int ll , int rr) { int res = 0; mf1(linker); for(int u=1; u<=uN; u++) { ms(used); if(!dfs(u, ll , rr)) return false; } return true; } bool check(int mid){ for(int i=0;i+mid<=100;i++){ if(hungry(mid, i, i+mid)){ return true; } } return false; } int main() { int T; scanf("%d", &T); while(T--) { int n; scanf("%d", &n); uN = vN = n; int mi = inf, ma = -1; for(int i=1; i<=n; i++) for(int j=1; j<=n; j++) { scanf("%d",&a[i][j]); mi = min(mi, a[i][j]); ma = max(ma, a[i][j]); } int l = 0, r = ma - mi; while(l<=r) { int mid = (l+r)>>1; if(check(mid)) { r = mid-1; } else l = mid+1; } printf("%d\n", l); } return 0; }