zoukankan      html  css  js  c++  java
  • CH6801 棋盘覆盖(二分图最大匹配)

    给定一个N行N列的棋盘,已知某些格子禁止放置。

    求最多能往棋盘上放多少块的长度为2、宽度为1的骨牌,骨牌的边界与格线重合(骨牌占用两个格子),并且任意两张骨牌都不重叠。

    输入格式

    第一行包含两个整数N和t,其中t为禁止放置的格子的数量。

    接下来t行每行包含两个整数x和y,表示位于第x行第y列的格子禁止放置,行列数从1开始。

    输出格式

    输出一个整数,表示结果。

    数据范围

    1≤N≤1001≤N≤100

    输出样例:

    8 0

    输出样例:

    32

    二分图最大匹配模板题。一块牌覆盖两个格子,可以看作连了一条边;横纵坐标之和为奇数的点以及为偶数的点构成的集合内部无边(因为骨牌不可能斜着放)。因此这是一张二分图,坐标和为奇数的点以及和为偶数的点分别为左部和右部,题目所求就是二分图的最大匹配,跑匈牙利算法即可。考虑到数据范围,可以用邻接矩阵存图,二维pair数组存匹配点。

    #include <bits/stdc++.h>
    using namespace std;
    int N, t, ans = 0;
    int mmap[105][105] = {0};
    bool vis[105][105];
    pair<int, int> match[105][105];
    int dir[4][2] = {{0, 1}, {0, -1}, {1, 0}, {-1, 0}};
    bool dfs(int x, int y)
    {
        for(int i = 0; i < 4; i++)
        {
            int nx = x + dir[i][0], ny = y + dir[i][1];
            if(nx >= 1 && nx <= N && ny >= 1 && ny <= N && !vis[nx][ny] && mmap[nx][ny] != -1)
            {
                vis[nx][ny] = 1;
                if(match[nx][ny].first == 0 && match[nx][ny].second == 0 || dfs(match[nx][ny].first, match[nx][ny].second))
                {
                    match[nx][ny].first = x, match[nx][ny].second = y;
                    return true;
                }
            }
        }
        return false;
    }
    int main()
    {
        cin >> N >> t;
        for(int i = 1; i <= N; i++) 
        {
            for(int j = 1; j <= N; j++) match[i][j].first = match[i][j].second = 0;
        }
        for(int i = 1; i <= t; i++) 
        {
            int x, y;
            cin >> x >> y;
            mmap[x][y] = -1;
        }
        for(int i = 1; i <= N; i++)
        {
            for(int j = 1; j <= N; j++)
            {
                if((i + j) & 1 || mmap[i][j] == -1) continue;//横纵坐标值和非奇数 
                memset(vis,0,sizeof(vis));
                //必须在确保一切条件都满足的情况下 才能进行dfs 
                if(dfs(i, j)) ans++;
            }
        }
        cout << ans;
        return 0;
    }
    #include <bits/stdc++.h>
    using namespace std;
    int N, t, ans = 0;
    int mmap[105][105] = {0};
    bool vis[105][105];
    pair<int, int> match[105][105];
    int dir[4][2] = {{0, 1}, {0, -1}, {1, 0}, {-1, 0}};
    bool dfs(int x, int y)
    {
        for(int i = 0; i < 4; i++)
        {
            int nx = x + dir[i][0], ny = y + dir[i][1];
            if(nx >= 1 && nx <= N && ny >= 1 && ny <= N && !vis[nx][ny] && mmap[nx][ny] != -1)
            {
                vis[nx][ny] = 1;
                if(match[nx][ny].first == 0 && match[nx][ny].second == 0 || dfs(match[nx][ny].first, match[nx][ny].second))
                {
                    match[nx][ny].first = x, match[nx][ny].second = y;
                    return true;
                }
            }
        }
        return false;
    }
    int main()
    {
        cin >> N >> t;
        for(int i = 1; i <= N; i++) 
        {
            for(int j = 1; j <= N; j++) match[i][j].first = match[i][j].second = 0;
        }
        for(int i = 1; i <= t; i++) 
        {
            int x, y;
            cin >> x >> y;
            mmap[x][y] = -1;
        }
        for(int i = 1; i <= N; i++)
        {
            for(int j = 1; j <= N; j++)
            {
                if((i + j) & 1 || mmap[i][j] == -1) continue;//横纵坐标值和非奇数 
                memset(vis,0,sizeof(vis));
                //必须在确保一切条件都满足的情况下 才能进行dfs 
                if(dfs(i, j)) ans++;
            }
        }
        cout << ans;
        return 0;
    }
  • 相关阅读:
    杨辉三角
    100以内的素数
    九九
    MyDate
    计算器
    100以内素数
    杨辉三角形
    九九乘法表
    窗口关闭事件
    计算器界面
  • 原文地址:https://www.cnblogs.com/lipoicyclic/p/13334094.html
Copyright © 2011-2022 走看看