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

    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<cstdio>
    #include<cstring>
    #define C(i,x) memset(i,x,sizeof(i))
    using namespace std;
    template<typename T>void read(T &x)
    {
        char ch;
        int f=1;
        x=0;
        for(; ch<'0'||ch>'9'; ch=getchar())
            if(ch=='-')
                f=-1;
        for(; ch>='0'&&ch<='9'; ch=getchar())
            x=(x<<1)+(x<<3)+(ch&15);
        x*=f;
    }
    template<typename T>void print(T x)
    {
        if(x<0)
            x*=-1,putchar('-');
        if(x>=10)
            print(x/10);
        putchar(x%10+'0');
    }
    const int N=200;
    const int INF=0x3f3f3f3f;
    int minn=INF;
    int p,mid=0;
    int nxe[N],used[N],mp[N][N];
    int n;
    bool Find(int x)
    {
        for(int i=0; i<n; i++)
        {
            if(!used[i]&&mp[x][i]>=p&&mp[x][i]<=p+mid)
            {
                used[i]=1;
                if(nxe[i]==-1||Find(nxe[i]))
                {
                    nxe[i]=x;
                    return true;
                }
            }
        }
        return false;
    }
    bool match()
    {
       C(nxe,-1);
      // memset(nxe,-1,sizeof(nxe));
        for(int i=0; i<n; i++)
        {
            C(used,0);
           // memset(used,0,sizeof(used));
            if(!Find(i))
            {
                return false;    //返回false ,若倒过来返回true 是错误的。
            }
        }
        return true;
    }
    int main()
    {
        ios::sync_with_stdio(false);
        int t;
        read(t);
        while(t--)
        {
            //cin>>n;
            read(n);
            int mx=-INF,mi=INF;
            for(int i=0; i<n; i++)
                for(int j=0; j<n; j++)
                {
                    read(mp[i][j]);
                    mx=max(mx,mp[i][j]);
                    mi=min(mi,mp[i][j]);
                }
            int l=0,r=mx-mi;
            int f=0;
            int res;
            while(l<=r)
            {
                mid=(l+r)>>1;
                f=0;
                for(p=mi; p+mid<=mx; p++)
                {
                    if(match())
                    {
                        f=1;
                        break;
                    }
                }
                if(f)
                    res=mid,r=mid-1;
                else
                    l=mid+1;
            }
            print(res);
            puts("");
        }
        return 0;
    }
    
    

    思路

    二分图的完美匹配。(行列分为两个集合,则每个顶点必定会被匹配到,否则匹配不到n个)

    二分查找差值;逐步缩小差值。

    ps

    要注意nxe数组初始化为-1; 因为点有0的值的情况,所以判断未匹配用-1表示。

  • 相关阅读:
    【数学】杜教筛
    【数学】【多项式】多项式求逆
    【数学】求导
    【数学】【多项式】快速数论变换(NTT)
    【数学】【多项式】快速傅里叶变换(FFT)
    WC2021 Day3 笔记
    网络流
    $DP$ 重修
    数学基础 5
    数学基础 3
  • 原文地址:https://www.cnblogs.com/xxffxx/p/11978519.html
Copyright © 2011-2022 走看看