题目描述:
这是一个简单的游戏,在一个n*n的矩阵中,找n个数使得这n个数都在不同的行和列里并且要求这n个数中的最大值和最小值的差值最小。
输入:
输入一个整数T表示T组数据。
对于每组数据第一行输入一个正整数n(1<=n<=100)表示矩阵的大小。
接着输入n行,每行n个数x(0<=x<=100)。
输出:
对于每组数据输出一个数表示最小差值。
样例输入:
1
4
1 1 1 1
2 2 2 2
3 3 3 3
4 4 4 4
样例输出:
3
code:
题目描述的很简单,也比较清晰
求不同行,不同列的n个数字,使得他们的最大与最小数字之间的差最小
很显然,二分+二分图匹配
在建图的时候,一直找不到到底是谁与谁进行比配
后来发现,以行为一组,列为一组,就能保证不同行,不同列了
建议在写本题之前看一下匈牙利算法
#include<iostream>
#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
const int maxn=150;
const int inf=0x3f3f3f3f;
int visit[maxn];
int match[maxn][maxn];
int pre[maxn];
int Max,Min;
int n;
bool dfs(int x){
for(int i=1;i<=n;i++){
if(visit[i]==0&&match[x][i]>=Min&&match[x][i]<=Max){
visit[i]=1;
if(pre[i]==0||dfs(pre[i])){
pre[i]=x;
return true;
}
}
}
return false;
}
bool findd(){
memset(pre,0,sizeof(pre));
for(int i=1;i<=n;i++){
memset(visit,0,sizeof(visit));
if(!dfs(i))return false;
}
return true;
}
int main()
{
int ttt;
scanf("%d",&ttt);
while(ttt--){
scanf("%d",&n);
memset(match,0,sizeof(match));
memset(pre,0,sizeof(pre));
int maxx=-1,minn=inf;
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
scanf("%d",&match[i][j]);
maxx=max(match[i][j],maxx);
minn=min(minn,match[i][j]);
}
}
int lb=-1,ub=maxx-minn+1,mid,flag;
while(ub-lb>1){
mid=(lb+ub)/2;
flag=0;
for(int i=0;i+mid<=maxx;i++){
Min=i;Max=i+mid;
if(findd()){
flag=1;
break;
}
}
if(flag)ub=mid;
else lb=mid;
}
printf("%d\n",ub);
}
return 0;
}