这是一个简单的游戏,在一个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;
}