• HDOJ2236 无题II[二分枚举+匈牙利]


    无题II

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


    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
     
    Author
    xhd
     
    Source
     
    Recommend
    lcy
     
     
     
     
     
     
     
     
    code :
      1 /*
      2 为了保证每行每列只取一个元素,我们可以从二分图最大匹配的思想入手,把行和列分别看做二分图左右两部分,
      3 i-j的边权就是第i行第j列的元素的值。这样构图之后,求得的二分图最大匹配的4条边就是不在同行或同列的4个元素。
      4 有了这个思想时候,我们只需要再保证4个元素中最大值与最小值之差尽量小就可以了,于是我们可以二分枚举最大值与最小值之差,
      5 并枚举边权值的下界,如果枚举到某个边权值的下界时该图存在最大匹配,那么就更新max,否则就更新min。
      6 */
      7 #include <iostream>   
      8 #include <iomanip>   
      9 #include <fstream>   
     10 #include <sstream>   
     11 #include <algorithm>   
     12 #include <string>   
     13 #include <set>   
     14 #include <utility>   
     15 #include <queue>   
     16 #include <stack>   
     17 #include <list>   
     18 #include <vector>   
     19 #include <cstdio>   
     20 #include <cstdlib>   
     21 #include <cstring>   
     22 #include <cmath>   
     23 #include <ctime>   
     24 #include <ctype.h> 
     25 using namespace std;
     26 
     27 #define MAXN 110
     28 
     29 int map[MAXN][MAXN];
     30 int vst[MAXN];
     31 int path[MAXN];
     32 int n;
     33 int p;
     34 int minnum,maxnum,midnum;
     35 
     36 bool dfs(int v)
     37 {
     38     for(int i=0;i<n;i++)
     39         if(map[v][i]>=p&&map[v][i]<=p+midnum&&!vst[i])
     40         {
     41             vst[i]=1;
     42             if(path[i]==-1||dfs(path[i]))
     43             {
     44                 path[i]=v;
     45                 return true;
     46             }
     47         }
     48     return false;
     49 }
     50 
     51 bool hungary()
     52 {
     53     memset(path,-1,sizeof(path));
     54     for(int i=0;i<n;i++)
     55     {
     56         memset(vst,0,sizeof(vst));
     57         if(!dfs(i))                                //一旦发现有横坐标没有对应的y坐标与其匹配就return false
     58             return false;
     59     }
     60     return true;                       //表示所有的横坐标已经全部匹配,return true
     61 }
     62 
     63 int main()
     64 {
     65     int t;
     66     int i,j;
     67     scanf("%d",&t);
     68     while(t--)
     69     {
     70         int gmax=0,gmin=101;
     71         scanf("%d",&n);
     72         for(i=0;i<n;i++)
     73             for(j=0;j<n;j++)
     74             {
     75                 scanf("%d",&map[i][j]);
     76                 gmax=gmax>map[i][j]?gmax:map[i][j];
     77                 gmin=gmin<map[i][j]?gmin:map[i][j];
     78             }
     79         maxnum=gmax-gmin;
     80         minnum=0;
     81         while(1)
     82         {
     83             bool flag=false;
     84             midnum=(maxnum+minnum)/2;
     85             for(p=gmin;p+midnum<=gmax;p++)
     86             {
     87                 if(hungary())
     88                 {
     89                     flag=true;
     90                     break;
     91                 }
     92             }
     93             if(flag)
     94                 maxnum=midnum;
     95             if(midnum==minnum)                  //注意:这三个if的顺序不能随意颠倒
     96                 break;
     97             if(!flag)
     98                 minnum=midnum;            
     99         }
    100         printf("%d\n",maxnum);
    101     }
    102     return 0;
    103 }
  • 相关阅读:
    数据结构实用C语言基础
    第二个星期的C语言
    hello world!
    代码规范
    调用有道词典翻译api
    PO,POJO,BO,DTO,VO的区别
    切换Eclipse语言包
    URI和URL区别
    get和post
    Eclipse快捷键
  • 原文地址:https://www.cnblogs.com/XBWer/p/2638207.html
Copyright © 2020-2023  润新知