zoukankan      html  css  js  c++  java
  • 无题II HDU

    题目

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

    分析

    首先就可以想到,如果对于找出来的n个数,刚好属于某个区间[l,r],那么显然可以得到答案就是r-l。所以我们直枚举所有可能的区间,然后二分图匹配,让所有可能的匹配权值都属于这个区间,如果成立,那么这个区间是可行的。

    然后就可以想到,对于答案来说是要找一个区间长度最小的区间,然后我们就二分一下,然后枚举所有长度为当前答案的区间,然后判断当前区间是否可行,如果当前区间可行,就说明当前答案正确,更新一下就完事了。

    代码

    #include <bits/stdc++.h>
    const int inf = 0x3f3f3f3f;
    using namespace std;
    const int maxn = 101;
    const int maxm = 10103;
    int umaxn, vmaxn;
    int a[maxn][maxn];
    bool us[maxn];
    int li[maxn];
    bool dfs(int u, int ll, int rr) {
        for(int v=1; v<=umaxn; v++) {
            if(a[u][v] >=ll && a[u][v]<=rr && !us[v]) {
                us[v] = true;
                if(li[v] == -1 || dfs(li[v], ll, rr)) {
                    li[v] = u;
                    return true;
                }
            }
        }
        return false;
    }
    bool ts(int mid, int ll , int rr) {
        int res = 0;
        memset(li,-1,sizeof(li));
        for(int u=1; u<=umaxn; u++) {
            memset(us,0,sizeof(us));
            if(!dfs(u, ll , rr)) return false;
        }
        return true;
    }
    bool check(int mid){
        for(int i=0;i+mid<=100;i++){
            if(ts(mid, i, i+mid)){
                return true;
            }
        }
        return false;
    }
    int main(){
        int T;
        scanf("%d", &T);
        while(T--){
            int n;
            scanf("%d", &n);
            umaxn = vmaxn = n;
            int Min = inf, Max = -1;
            for(int i=1; i<=n; i++)
                for(int j=1; j<=n; j++){
                    scanf("%d",&a[i][j]);
                    Min = min(Min, a[i][j]);
                    Max = max(Max, a[i][j]);
                }
            int l = 0, r = Max - Min;
            while(l<=r) {
                int mid = (l+r)>>1;
                if(check(mid)){
                    r = mid-1;
                } else l = mid+1;
            }
            printf("%d
    ", l);
        }
        return 0;
    }
  • 相关阅读:
    绿茶一杯辨蜂蜜
    将Windows桌面扩展到第二个显示器/投影机上
    各种茶的特点和挑选(未完)
    转载一位操盘手的惊人语录 
    大家看看这个资料,有助于你了解股市
    庄家的故事之000503海虹控股
    股本变迁,分红扩股数据调查
    onchange 和 onkeyup,onpropertychange 用法小记
    对范美忠事件的评论
    一位天涯的朋友在星期一晚上发来的留言
  • 原文地址:https://www.cnblogs.com/Vocanda/p/12882883.html
Copyright © 2011-2022 走看看