Problem Description
Some 1×2 dominoes are placed on a plane. Each dominoe is placed either horizontally or vertically. It's guaranteed the dominoes in the same direction are not overlapped, but horizontal and vertical dominoes may overlap with each other. You task is to remove some dominoes, so that the remaining dominoes do not overlap with each other. Now, tell me the maximum number of dominoes left on the board.
Input
There are multiple input cases.
The first line of each case are 2 integers: n(1 <= n <= 1000), m(1 <= m <= 1000), indicating the number of horizontal and vertical dominoes.
Then n lines follow, each line contains 2 integers x (0 <= x <= 100) and y (0 <= y <= 100), indicating the position of a horizontal dominoe. The dominoe occupies the grids of (x, y) and (x + 1, y).
Then m lines follow, each line contains 2 integers x (0 <= x <= 100) and y (0 <= y <= 100), indicating the position of a horizontal dominoe. The dominoe occupies the grids of (x, y) and (x, y + 1).
Input ends with n = 0 and m = 0.
Output
For each test case, output the maximum number of remaining dominoes in a line.
Sample Input
2 3
0 0
0 3
0 1
1 1
1 3
4 5
0 1
0 2
3 1
2 2
0 0
1 0
2 0
4 1
3 2
0 0
Sample Output
4
6 題目大意:給你兩種紙牌 ,一種水平放置共有n張 ,一種豎直放置共有m張。水平放置的紙牌占據點(x, y)和(x + 1 , y) , 豎直放置的紙牌占據點(x , y) 和 (x , y + 1)。水平放置的牌之間不會重疊,豎直放置的牌之間也不會重疊,但是水平放置的牌和豎直放置的牌之間可能會重疊。讓你拿走一些牌,使剩下的牌之間不會重疊並且數量最多,輸出剩余的最大牌數。 解題思路:這是一道典型的二分圖匹配問題,先是建圖:水平放置的牌放入集合ho{}中,豎直放置的牌放入集合ve{}中,重疊的牌之間建立一條邊。圖建好後,求出圖的最大匹配數 , 然後由二分圖的點獨立數 = 頂點個數 - 匹配數 得到點獨立數 即是答案。 請看代碼:
#include<iostream> #include<cstring> #include<string> #include<cmath> #include<cstdio> #include<algorithm> using namespace std ; const int MAXN = 1111 ; struct point { int x ; int y ; } ho[MAXN] , ve[MAXN]; int g[MAXN][MAXN] ; int cx[MAXN] ; int cy[MAXN] ; int vis[MAXN] ; int n , m ; int path(int v) // 匈牙利算法 { int i ; for(i = 0 ; i < m ; i ++) { if(g[v][i] == 1 && !vis[i]) { vis[i] = 1 ; if(cy[i] == -1 || path(cy[i])) { cy[i] = v ; cx[v] = i ; return 1 ; } } } return 0 ; } int pi(point a , point b) // 判斷是否重疊 { if(a.x == b.x && a.y == b.y) return 1 ; if(a.x == b.x && a.y == b.y + 1) return 1 ; if(a.x + 1 == b.x && a.y == b.y) return 1 ; if(a.x + 1 == b.x && a.y == b.y + 1) return 1 ; return 0 ; } void init() { while (cin >> n >> m) { if(n == 0 && m == 0) break ; memset(g , 0 , sizeof(g)) ; memset(cx , -1 , sizeof(cx)) ; // 均初始化為-1 ,代表此點未被覆蓋 memset(cy , -1 , sizeof(cy)) ; int i , j ; for(i = 0 ; i < n ; i ++) { scanf("%d%d" , &ho[i].x , &ho[i].y) ; } for(j = 0 ; j < m ; j ++) { scanf("%d%d" , &ve[j].x , &ve[j].y) ; } for(i = 0 ; i < n ; i ++) { for(j = 0 ; j < m ; j ++) if(pi(ho[i] , ve[j])) { g[i][j] = 1 ; // 建圖,注意這裡千萬不能寫成 g[i][j] = g[j][i] = 1 !! } } int ans = 0 ; // 記錄匹配數 for(i = 0 ; i < n ; i ++) { if(cx[i] == -1) // 如果 第i張 水平放置 的牌未被覆蓋 , 就從此點出發尋找增廣路 { memset(vis , 0 ,sizeof(vis)) ; ans += path(i) ; } } printf("%d\n" , n + m - ans) ; } } int main() { init() ; return 0 ; }