Sicily 7693. Cards 解题报告

题目传送门:7693. Cards

 

思路:

1.  用数组b[m]和r[n]表示两组卡片,开一个bool类型的矩阵match,match[i][j]为true则表示b[i]和r[j]可以组成一对。

2.  要得到最多的匹配对数,从最优的感觉上来看可以求出每张卡片在另一组有多少卡片与之匹配,然后每次从蓝色组中找出匹配数最少的那张卡,并在与那张卡匹配的红组卡中找出匹配数最少的那一张组成一队消除。这样考虑的理由是:匹配数多是卡即使消去了与之匹配的其中一些卡,还有剩下的卡可以匹配,因此先消去匹配数最小的卡。

3.  为了找到当前匹配数最少的那2张卡,开数组num_of_matches_b[m]记录每张蓝色卡当前的匹配数,num_of_matched_r[n]记录每张红色卡当前的匹配数。匹配数若为0则表示另一组没有卡与该卡组成一对。每次从蓝色卡中找出匹配数最小且非零的那张,记录下标index_b,然后从与之匹配的红色卡中找出匹配数最小的那张,记录下标index_r。将该对消除后,match[i][j]变为false,并将于这两张卡匹配的所有卡的匹配数减一(因为这两张卡已经不能再利用)。

 

代码:

 1 #include <iostream>
 2 #include <memory.h>
 3 using namespace std;
 4 
 5 int gcd(int x, int y){
 6     int temp;
 7     if(x < y){
 8         temp = x, x = y, y = temp;
 9     }
10     while(y != 0){
11         temp = x % y, x = y, y = temp;
12     }
13     return x;
14 }
15 bool match(const int &a, const int &b){
16     if(gcd(a, b) > 1)
17         return true;
18     else
19         return false;
20 }
21 
22 int main(){
23     int m, n;
24     while(cin >> m >> n && (m != 0 || n != 0)){
25         int b[m], r[n], num_of_matches_b[m], num_of_matches_r[n];
26         bool match_matrix[m][n];//match_matrix[i][j] will be true if b[i] match r[j].
27         memset(num_of_matches_b, 0, sizeof(num_of_matches_b));
28         memset(num_of_matches_r, 0, sizeof(num_of_matches_r));
29         for(int i = 0; i < m; ++i){
30             memset(match_matrix[i], false, sizeof(match_matrix[i]));
31         }
32         for(int i = 0; i < m; ++i)
33             cin >> b[i];
34         for(int i = 0; i < n; ++i)
35             cin >> r[i];
36         for(int i = 0; i < m; ++i){
37             for(int j = 0; j < n; ++j){
38                 if(match(b[i], r[j])){
39                     match_matrix[i][j] = true;
40                     num_of_matches_b[i]++;
41                     num_of_matches_r[j]++;
42                 }
43             }
44         }
45         int min = n + 1,  //The most matches of a blue card will not exceed n.
46         result = 0, index_b, index_r;//b[index_b] and r[index_r] is the pair of cards to be removed.
47         for(int i = 0; i < m; ++i){//find index_b
48             if(num_of_matches_b[i] > 0 && num_of_matches_b[i] < min){
49                 min = num_of_matches_b[i];
50                 index_b = i;
51             }
52         }
53         if(min == n + 1)  //No such pair
54             cout << 0 << endl;
55         else{
56             while(min != n + 1){
57                 result++;
58                 //There still exist one pair at least.
59                 min = m + 1;  //The most matches of a red card will not exceed m.
60                 for(int i = 0; i < n; ++i){//Find index_r
61                     if(match_matrix[index_b][i] && num_of_matches_r[i] < min){
62                         index_r = i;
63                         min = num_of_matches_r[i];
64                     }
65                 }
66                 for(int i = 0; i < m; ++i){
67                     if(match_matrix[i][index_r]){
68                         num_of_matches_b[i]--;
69                         match_matrix[i][index_r] = false;
70                     }
71                 }
72                 for(int i = 0; i < n; ++i){
73                     if(match_matrix[index_b][i]){
74                         match_matrix[index_b][i] = false;
75                         num_of_matches_r[i]--;
76                     }
77                 }
78                 num_of_matches_b[index_b] = 0;
79                 num_of_matches_r[index_r] = 0;
80                 //Renew min
81                 min = n + 1;
82                 for(int i = 0; i < m; ++i){
83                     if(num_of_matches_b[i] > 0 && num_of_matches_b[i] < min){
84                         min = num_of_matches_b[i];
85                         index_b = i;
86                     }
87                 }
88             }
89             cout << result << endl;
90         }
91     }
92     return 0;
93 }
原文地址:https://www.cnblogs.com/jolin123/p/3633135.html