程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> C++入門知識 >> HDU 4619 Warm up 2 (2013 多校第二場) - from lanshui_Yang

HDU 4619 Warm up 2 (2013 多校第二場) - from lanshui_Yang

編輯:C++入門知識

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 ;
}

 

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved