zoukankan      html  css  js  c++  java
  • HDU-4185 Oil Skimming(二分匹配,匈牙利算法)

    题意:给出一个N*N图,#表示有油,.表示水。现在要统计最多有多少块符合条件的油田
    条件:油田不能重合,为1 x 2 的矩形,可以竖着1x2也可以横着1x2。
    思路:我们可以把所有的油田看作一个单独的块,匹配时就搜索当前块上下左右相邻是否有油田
    实际上就是 油田作为一个点,两两相邻的点符合条件就连接一条边。然后用二分图的匹配形式去找到最大匹配
    同时这种最大匹配实际上有重复(连成无相图了),所以最后还要除以2

    完整代码:

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    using namespace std;
    const int maxm = 1e4;
    const int maxn = 1005;
    char G[maxn][maxn];
    int bmap[maxn][maxn];
    int cur[maxn][maxn];
    int n;
    int cnt ; 
    int match[maxn];//表示匹配关系(左集合到右集合的匹配)
    int vis[maxn];//表示是否被访问过
    //记录匹配个数
    bool Find(int u){
           for(int i = 0;i<cnt;i++){
               int v = i;
               if(!vis[v]&&bmap[u][v]){
                vis[v] = 1;
                if(!match[v]||Find(match[v])){
                    match[v] = u;
                    return true;
                }
            }
        }   
        return false;
    }
    int hungary(){
        int count = 0;
        memset(match,0,sizeof(match));
        for(int i =0;i<cnt;i++){
            memset(vis,0,sizeof(vis));
            if(Find(i)) count++;
        }
        return count;
    }
    
    int main(){
        int T;
        cin>>T;
        int cas = 0;
        while(T--){
            memset(G,0,sizeof(G));
            cnt = 0;
            cin>>n;
            for(int i =0;i<n;i++){
                cin>>G[i];
            }
            for(int i =0 ;i<n;i++){
                for(int j =0;j<n;j++){
                    if(G[i][j]=='#') cur[i][j] = cnt++;
                }
            }
            memset(bmap,0,sizeof(bmap));
            for(int i =0;i<n;i++){
                for(int j = 0;j<n;j++){
                    if(G[i][j]!='#') continue;
                    if(i>0&&G[i-1][j]=='#') bmap[cur[i][j]][cur[i-1][j]] = 1;
                    if(i<n-1&&G[i+1][j]=='#') bmap[cur[i][j]][cur[i+1][j]] = 1;
                    if(j>0&&G[i][j-1]=='#') bmap[cur[i][j]][cur[i][j-1]] = 1;
                    if(j<n-1&&G[i][j+1]=='#') bmap[cur[i][j]][cur[i][j+1]] = 1;
                }
            }
            int num = hungary();
            cout<<"Case "<<++cas<<": "<<num/2<<endl;
        }    
    }
  • 相关阅读:
    CF666E. Forensic Examination
    bzoj1396 识别子串
    bzoj2839 集合计数
    unknown
    Hibernate中一级缓存和二级缓存
    亲, 我们来再重申一遍"=="和"equals的区别
    BigDecimal类
    序列化详解
    利用简单的参数传递来实现单条查询的easyui-datagrid
    Oracl 动态执行表不可访问,本会话的自动统计被禁止
  • 原文地址:https://www.cnblogs.com/Tianwell/p/11340387.html
Copyright © 2011-2022 走看看