码迷,mamicode.com
首页 > 其他好文 > 详细

无题II(二分 + 匈牙利匹配)

时间:2020-05-14 13:29:19      阅读:60      评论:0      收藏:0      [点我收藏+]

标签:sam   memset   大小   script   游戏   整数   match   name   namespace   

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
——————————————————————————————————————————————————————————————————

首先,先明确,对于所取的每一个数,它的行和列一一对应,不会重复对应,于是将行数字和列数字看做A,B部,每个数字即连线,这是一个二分图

然后二分差值,从最小值一直枚举差值区间,看是不是能够找到完美匹配
——————————————————————————————————————————————————————————————————

代码:

 1 #include<cstdio>
 2 #include<iostream>
 3 #include<cstring>
 4 #include<cstdlib>
 5 #include<algorithm>
 6 using namespace std;
 7 const int INF = 0x3f3f3f3f;
 8 const int Max = 105;
 9 int maxn,maxm,down,mid;
10 int match[Max];
11 int map[Max][Max];
12 bool vis[Max];
13 void getint(int & num){  
14     char c; int flg = 1;    num = 0;  
15     while((c = getchar()) < 0 || c > 9)   if(c == -)    flg = -1;  
16     while(c >= 0 && c <= 9){  num = num * 10 + c - 48;    c = getchar();}  
17     num *= flg;  
18 }  
19 int max(int a, int b){    return a < b ? b : a;}
20 int min(int a, int b){    return a < b ? a : b;}
21 bool HUN(int x){
22     for(int i = 1; i <= maxn; ++ i)    if(map[x][i] >= down && map[x][i] <= down + mid && ! vis[i]){
23         vis[i] = 1;
24         if(! match[i] || HUN(match[i])){
25             match[i] = x;
26             return 1;
27         }
28     }
29     return 0;
30 }
31 bool checkk(){
32     memset(match, 0, sizeof(match));
33     for(int i = 1; i <= maxn; ++ i){
34         memset(vis, 0, sizeof(vis));
35         if(! HUN(i))    return 0;
36     }
37     return 1;
38 }
39 int main(){
40     //freopen("a.in","r",stdin);
41     int T;getint(T);
42     while(T --){
43         getint(maxn);
44         int maxv = -INF, minv = INF;
45         for(int i = 1; i <= maxn; ++ i)
46             for(int j = 1; j <= maxn; ++ j){
47                 getint(map[i][j]);
48                 maxv = max(maxv, map[i][j]);
49                 minv = min(minv, map[i][j]);
50             }
51         int l = 0, r = maxv - minv, rt;
52         while(l <= r){
53             mid = (l + r) >> 1;
54             bool flg = 0;
55             for(down = minv; down + mid <= maxv; ++ down)
56                 if(checkk()){
57                     flg = 1;
58                     break;
59                 }
60             if(flg)    rt = mid, r = mid - 1;
61             else l = mid + 1;
62         }
63         printf("%d\n", rt);
64     }
65     return 0;
66 }

 

无题II(二分 + 匈牙利匹配)

标签:sam   memset   大小   script   游戏   整数   match   name   namespace   

原文地址:https://www.cnblogs.com/DZN2004/p/12887867.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!