题目传送门: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 }