HDU 1045 Fire Net 二分图匹配 经典建图方法

HDU 1045 Fire Net 二分图匹配 经典建图方法

题目来源:

题意:

找到图中可以安放堡垒并不会互相攻击的位置方案数。(堡垒向4个方向发射子弹,并且墙可以挡下子弹)

题解:

分析:

要达到题目的要求,只要找到可以满足覆盖所有的空白的放置方案即可。那么便可以将题目转变为二分图最大匹配。

主要解题方案:二分图最大匹配+(一行变多行,一列变多列建图方法)

当然,这题数据不大,也可以使用DFS暴力搜一遍过去。

参考资料:百度文库

代码:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cstdio>
#include <cmath>
typedef long long ll;
typedef unsigned long long ull;
using namespace std;
char mp[50][50];
int n;
int row[50][50],col[50][50],r[50],c[50];
int cnt_c,cnt_r;
bool G[50][50];
bool vi[50];

int dfs(int x)
{
    for(int i=0;i<cnt_c;i++)
    {
        if(G[x][i] && !vi[i])
        {
            vi[i]=1;
            if(c[i]==-1||dfs(c[i]))
            {
                c[i]=x;
                r[x]=i;
                return 1;
            }
        }
    }
    return 0;
}

int match()    //匈牙利算法
{
    int ans=0;
    memset(r,-1,sizeof(r));
    memset(c,-1,sizeof(c));
    for(int i=0;i<cnt_r;i++)
        if(r[i]==-1)
        {
            memset(vi,0,sizeof(vi));
            ans+=dfs(i);
        }
    return ans;
}

int main()
{
#ifndef ONLINE_JUDGE
   // freopen("test.in","r",stdin);
    //freopen("test.out","w",stdout);
#endif
    while(cin >> n && n)
    {
        memset(row,-1,sizeof(row));
        memset(col,-1,sizeof(col));
        cnt_c=cnt_r=0;
        for(int i=0;i<n;i++)
            cin >> mp[i];
        for(int i=0;i<n;i++)    //建图过程1
        {
            for(int j=0;j<n;j++)
            {
                if(mp[i][j] == '.' && row[i][j]==-1)
                {
                    for(int k=j;mp[i][k]=='.'&& k<n;k++)
                        row[i][k]=cnt_r;
                    cnt_r++;
                }
                if(mp[j][i]=='.' && col[j][i]==-1)
                {
                    for(int k=j;mp[k][i]=='.'&& k<n;k++)
                        col[k][i]=cnt_c;
                    cnt_c++;
                }
            }
        }
        memset(G,0,sizeof(G));
        for(int i=0;i<n;i++)    //建图过程2
            for(int j=0;j<n;j++)
                if(mp[i][j]=='.')
                    G[row[i][j]][col[i][j]]=1;
        cout << match() << endl;
    }
    return 0;
}

转载于:https://www.cnblogs.com/Combustible-ice/p/5893880.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值