無題II

題目鏈接

題目描述:

這是一個簡單的遊戲,在一個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;
 } 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章