当前位置:编程学习 > C/C++ >>

HDU 1507 Uncle Tom's Inherited Land(黑白棋盘最大匹配)

[cpp] 
/*
题意:N*M的矩形,向其中填充1*2的小块矩形,黑色的部分不能填充,问最多可以填充多少块。
 
题解:黑白棋最大匹配
将棋盘中i+j为奇数的做A集合,偶数的做B集合,相邻的则建立联系。于是便转换成寻找最大匹配的问题
*/ 
 
#include <iostream> 
#define re(i, n) for(int i = 0; i < n; ++ i) 
using namespace std; 
 
const int nMax = 105; 
const int mMax = 10010; 
int N, M, K; 
int map[nMax][nMax];//存储图中的数据 
int G[mMax][5];//G[k][]表示与k = i * M + j相连的可填充点,邻接表建立AB集合之间的联系 
int link[mMax]; 
int useif[mMax]; 
int num;//最大匹配数 
int V;// N * M :总节点数 
 
void buildGraph()//建图,对G进行处理 

    memset(G, -1, sizeof(G)); 
    re(i, N) re(j, M) 
    { 
        int u = i * M + j; 
        int v = 0; 
        if(!map[i][j] && ((i + j) & 1) == 1)//此点可填充,并且i+j为奇数 
        { 
            //左 
            if(j > 0 && !map[i][j - 1]) 
            { 
                G[u][v ++] = u - 1; 
            } 
            //右 
            if(j < M - 1 && !map[i][j + 1]) 
            { 
                G[u][v ++] = u + 1; 
            } 
            //上 
            if(i > 0 && !map[i - 1][j]) 
            { 
                G[u][v ++] = u - M; 
            } 
            //下 
            if(i < N - 1 && !map[i + 1][j]) 
            { 
                G[u][v ++] = u + M; 
            } 
        } 
    } 

 
int dfs(int t) 

    for(int i = 0; G[t][i] != -1; ++ i) 
    { 
        int u = G[t][i]; 
        if(!useif[u])//因为邻接表结构,所以t、u肯定有联系,无需在进行map[][]判断 
        { 
            useif[u] = 1;  www.zzzyk.com
            if(link[u] == -1 || dfs(link[u])) 
            { 
                link[u] = t; 
                return 1; 
            } 
        } 
    } 
    return 0; 

 
int maxMatch() 

    num = 0; 
    memset(link, -1, sizeof(link)); 
    re(i, V) 
    { 
        memset(useif, 0, sizeof(useif)); 
        if(dfs(i)) 
            num ++; 
    } 
    return num; 

 
int main() 

    //freopen("f://data.in", "r", stdin); 
    while(scanf("%d %d", &N, &M) != EOF) 
    { 
        if(!N && !M) break; 
        scanf("%d", &K); 
        memset(map, 0, sizeof(map)); 
        re(i, K)  
        { 
            int a, b; 
            scanf("%d %d", &a, &b); 
            map[a - 1][b - 1] = 1; 
        } 
        V = N * M; 
        buildGraph(); 
        maxMatch(); 
        printf("%d\n", num); 
        re(i, V) 
        { 
            if(link[i] != -1)//因为最大匹配,所以不会有重复,查找一次,然后输出即可 
            { 
                int u = link[i]; 
                printf("(%d,%d)--(%d,%d)\n", u / M + 1, u % M + 1, i / M + 1, i % M + 1); 
            } 
        } 
        printf("\n"); 
    } 
    return 0; 

作者:lhshaoren
补充:软件开发 , C++ ,
CopyRight © 2022 站长资源库 编程知识问答 zzzyk.com All Rights Reserved
部分文章来自网络,