无题II hdu-2236

这是一个简单的游戏,在一个n*n的矩阵中,找n个数使得这n个数都在不同的行和列里并且要求这n个数中的最大值和最小值的差值最小。

这道题是道不错的二分图题
首先要对答案进行二分了,这个很自然就想到了;
但在后面对二分是否符合的判断思路卡住了
后面才想到使用枚举从(最小值,最小值+二分的差值)枚举这个区间进行行列匹配。好题!!!
详情见如下代码

#include <cstdio>
#include <algorithm>
#include <cstring>
#include <vector> 
#include <queue>
using namespace std;
const int N=3e3+10;
const int M=1e7+10;
const int inf=0x3f3f3f3f;
int head[N],cnt;
struct edge{
	int next,to;
}e[M];
void add(int u,int v){
	e[cnt].to=v;
	e[cnt].next=head[u];
	head[u]=cnt++;
}
int mp[105][105],minn,maxn,n;
bool vis[N];
int match[N];
bool dfs(int x,int l,int r){
	for(int i=1;i<=n;++i){
		if(!vis[i]&&mp[x][i]>=l&&mp[x][i]<=r){
			vis[i]=1;
			if(match[i]==-1||dfs(match[i],l,r)){
				match[i]=x;
				return true;
			}
		}
	}
	return false;
}
bool solve(int l,int r){
	memset(match,-1,sizeof match);
	for(int i=1;i<=n;++i){
		memset(vis,false,sizeof vis);
		if(!dfs(i,l,r)) return false; 
	}
	return true;
}
bool check(int t){
	for(int i=minn;i<=maxn-t;++i){
		if(solve(i,i+t)) return true;
	}
	return false;
}
int main(){
	int T;scanf("%d",&T);
	while(T--){
		scanf("%d",&n);
		minn=inf,maxn=0;
		for(int i=1;i<=n;++i){
			for(int j=1;j<=n;++j){
				scanf("%d",&mp[i][j]);
				minn=min(minn,mp[i][j]);
				maxn=max(maxn,mp[i][j]);
			}
		} 
		int l=0,r=maxn-minn,ans;
		while(l<=r){
			int mid=l+r>>1;
			if(check(mid)){
				r=mid-1,ans=mid;
			}
			else l=mid+1;
		}
		printf("%d\n",ans);
	}
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值