• HDU 1045 最大匹配


    xg

    题意

      给了一个4*4矩阵。图中有的点代表山。要求在这个矩阵上放碉堡,碉堡可以上下,左右攻击所能看到的碉堡,山可以阻挡两边碉堡互相看到,且碉堡不能放到山上。问最多可以放多少个碉堡。

    思路

      数据范围小可以暴力。

      但是用最大匹配解:

      在矩阵上的最大匹配问题,可以转化为x,y坐标的最大匹配。

      因为碉堡能进行格挡,则可以把x,y行问题转化为一块一块。

      

      上图是x坐标的块,然后和y的块建图最大匹配即可。

    #include <iostream>
    #include <cmath>
    #include <cstdio>
    #include <cstring>
    #include <string>
    #include <map>
    #include <iomanip>
    #include <algorithm>
    #include <queue>
    #include <stack>
    #include <set>
    #include <vector> 
    
    #define bug cout<<"--------------"<<endl
    #define sp ' '
    using namespace std;
    typedef long long ll;
    
    const int maxn = 100;
    int n;
    int a[maxn][maxn];
    int tot = 0;
    int head[maxn],ver[maxn],edge[maxn],nextt[maxn];
    void add(int x,int y)
    {
        ver[++tot] = y,nextt[tot] = head[x] , head[x] = tot;
    }
    int match[maxn],vis[maxn];
    bool dfs(int x)
    {
        for(int i = head[x],y;i; i = nextt[i]){    
            if(!vis[y = ver[i]]){
                vis[y] = 1;
                if(!match[y] || dfs(match[y])){
                    match[y] = x; return 1;
                }
            }
        }
        return 0;
    }
    int main()
    {
        //freopen("input.txt", "r", stdin);
        while(scanf("%d",&n) != EOF){
            if(n == 0) break;
            int cnt = 0;
            memset(a,0,sizeof(a));
            memset(head,0,sizeof(head));
            memset(match,0,sizeof(match));
            tot = 0;
            for(int i = 1; i<=n;++i){
                for(int j=1;j<=n;++j){
                    char c;
                    cin>>c;
                    if(c == '.') a[i][j] = 1;
                }
            }
            for(int i = 1;i<=n;++i){
                for(int j = 1;j <=n;++j){
                    if(a[i][j]){
                        if(a[i][j-1] == 0) cnt++;
                        a[i][j] = cnt;
                    }
                }
            }
            int nub = cnt;
            for(int j = 1;j <=n;++j){
                for(int i = 1;i<=n;++i){
                    if(a[i][j]){
                        if(a[i-1][j] == 0) cnt++;
                        add(a[i][j],cnt);
                        //add(cnt,a[i][j]);
                    }
                }
            }
            int ans = 0;
            for(int i = 1;i <= nub;++i){
                memset(vis,0,sizeof(vis));
                if(dfs(i)) ans++;
            } 
            printf("%d
    ",ans );
            //bug;
    
        }
    }
  • 相关阅读:
    2020-08-11 题目题解
    N皇后问题
    逆序对(模板)
    归并选择(模板)
    快速选择(模板)
    快速排序(模板)
    vuecli4+elementui实现面包屑
    vue-路由导航(守卫)那些事
    vue-vant中ImagePreview 图片预览正确的打开方式
    Selenium 对表格table处理
  • 原文地址:https://www.cnblogs.com/jrfr/p/13552328.html
Copyright © 2020-2023  润新知