hdu1045 Fire Net (二分图匹配)

分析:

这题的弱化版:ch6802 車的放置

两题的区别在于ch6802禁止的点只是不能放,但是车还是能穿过去的,因此一行最多只能放一个
而hdu1045,也就是这题,禁止的地方是墙,能把两个车隔开
容易想到有墙的存在,一行就可能放两个甚至多个车

如果没有墙,每行共用一个节点标记也就是行数,
有墙的话只要把墙隔开的两边各自标记就行了。
列同理

ps:这题做完之后好像又懂了一点

code:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<vector>
typedef long long ll;
const int inf=0x3f3f3f3f;
const int inn=0x80808080;
using namespace std;
const int maxm=20;
char s[maxm][maxm];
int h[maxm][maxm];//标记行
int l[maxm][maxm];//标记列
vector<int>g[maxm];//存图
int n;
int nn;//行节点总数
int mark[maxm];
int now[maxm];
int dfs(int u){
    for(int i=0;i<(int)g[u].size();i++){
        int v=g[u][i];
        if(!mark[v]){
            mark[v]=1;
            if(now[v]==0||dfs(now[v])){
                now[v]=u;
                return 1;
            }
        }
    }
    return 0;
}
int main(){
    while(cin>>n&&n){
        getchar();
        for(int i=1;i<=n;i++){
            for(int j=1;j<=n;j++){
                s[i][j]=getchar();
            }
            getchar();
        }
        int cnt=1;
        memset(h,0,sizeof h);
        memset(l,0,sizeof l);
        for(int i=1;i<=n;i++){//行标记
            for(int j=1;j<=n;j++){
                if(s[i][j]=='.'&&h[i][j]==0){
                    for(int k=j;k<=n;k++){//同一块的标记相同数字
                        if(s[i][k]=='X'){
                            break;
                        }
                        h[i][k]=cnt;
                    }
                    cnt++;
                }
            }
        }
        nn=cnt-1;//记录行标记总数量
        cnt=1;
        for(int i=1;i<=n;i++){//列标记
            for(int j=1;j<=n;j++){
                if(s[j][i]=='.'&&l[j][i]==0){
                    for(int k=j;k<=n;k++){//同一块的标记相同数字
                        if(s[k][i]=='X'){
                            break;
                        }
                        l[k][i]=cnt;
                    }
                    cnt++;
                }
            }
        }
        for(int i=1;i<=nn;i++){//清空,注意要清空到nn而不是n
            g[i].clear();
        }
        for(int i=1;i<=n;i++){
            for(int j=1;j<=n;j++){
                if(s[i][j]=='.'){
                    g[h[i][j]].push_back(l[i][j]);
                }
            }
        }
        memset(now,0,sizeof now);
        int ans=0;
        for(int i=1;i<=nn;i++){//直接匈牙利
            memset(mark,0,sizeof mark);
            ans+=dfs(i);
        }
        cout<<ans<<endl;
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/weixin_44178736/article/details/92581199