HDU 2236 无题II(二分匹配模板题,匈牙利算法)

135 篇文章 0 订阅
109 篇文章 0 订阅
无题II

Time Limit: 2000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 1635    Accepted Submission(s): 751

Problem Description
这是一个简单的游戏,在一个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 4
 
Sample Output
3
 
二分来遍历所有可能的最小差值,二分匹配就是模板题

 

#include <iostream>
#include <cstring>
using namespace std;
const int N = 110;  
const int inf = 0x3f3f3f3f;  
int num[N],mapp[N][N];
int p,mid,n;
bool vis[N],flag;
bool dfs(int v){
    for(int i=0;i<n;i++){
        if(mapp[v][i]>=p&&mapp[v][i]<=p+mid&&(!vis[i])){
            vis[i]=true;
            if(num[i]==-1||dfs(num[i])){
                num[i]=v;
                return true;
            }
        }
    }
    return false;
} 
bool solve(){
    memset(num,-1,sizeof(num));
    for(int i=0;i<n;i++){
        memset(vis,0,sizeof(vis));
        if(!dfs(i)){
            return false;
        }
    }
    return true;
}
int main(){
    cin.sync_with_stdio(false);
    int T;
    cin>>T;
    while(T--){
        cin>>n;
        int vmax=-inf,vmin=inf;
        for(int i=0;i<n;i++){
            for(int j=0;j<n;j++){
                cin>>mapp[i][j];
                vmax=max(vmax,mapp[i][j]);
                vmin=min(vmin,mapp[i][j]);
            }
        }
        int r=vmax-vmin,l=0,res;
        while(l<=r){
            mid=(l+r)>>1;
            flag=false;
            for(p=vmin;p+mid<=vmax;p++){
                if(solve()){
                    flag=true;
                    break;
                }
            }
            if(flag){
                res=mid;
                r=mid-1;
            }
            else{
                l=mid+1;
            }
        }
        cout<<res<<endl;
    }
    return 0;
}

2017-02-28 22:06:36
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值