POJ 2226 Muddy Fields (最小点覆盖)

题意:一个row*col的矩阵表示一块田地,'*'表示湿地,'.'表示草地。现在FJ要在田地上铺木板盖掉所有的湿地,露出所有的草地。每块木板的宽度为1,长度为任意长。问FJ最少用几块木板就可以完成任务?


思路:匈牙利算法的最小点覆盖。将每行所含有的每一段做为一侧的点,将每列所含有的每一段作为另一侧的点,就是对每一段'*'赋给一个新的x,y坐标,使得不同的段x,y不同。

#include <cstdio>
#include <iostream>
#include <cstring>
#include <string>
#include <cstdlib>
#include <algorithm>
#include <cmath>
#include <vector>
#include <set>
#include <list>
#include <queue>
#include <map>
using namespace std;
#define L(i) i<<1
#define R(i) i<<1|1
#define INF  0x3f3f3f3f
#define pi acos(-1.0)
#define eps 1e-3
#define maxn 100010
#define MOD 1000000007

int n,m,t1,t2;
char s[5050][5050];
int mp[5050][5050];
int mx[5050][5050],my[5050][5050];
int match[5050],vis[5050];

int dfs(int x)
{
    for(int i = 1; i < t2; i++)
        if(mp[x][i] && !vis[i])
        {
            vis[i] = 1;
            if(!match[i] || dfs(match[i]))
            {
                match[i] = x;
                return 1;
            }
        }
    return 0;
}
int main()
{
    int t,C = 1;
    //scanf("%d",&t);
    while(scanf("%d%d",&n,&m) != EOF)
    {
        memset(match,0,sizeof(match));
        for(int i = 0; i < n; i++)
            scanf("%s",s[i]);
        t1 = 1,t2 = 1;
        for(int i = 0; i < n; i++)
        {
            if(s[i][0] == '*')
                mx[i][0] = t1;
            for(int j = 1; j < m; j++)
            {
                if(s[i][j] == '*')
                    mx[i][j] = t1;
                else if(s[i][j-1] == '*')
                    t1++;
            }
            if(s[i][m-1] == '*')
                t1++;
        }
        for(int i = 0; i < m; i++)
        {
            if(s[0][i] == '*')
                my[0][i] = t2;
            for(int j = 1; j < n; j++)
            {
                if(s[j][i] == '*')
                    my[j][i] = t2;
                else if(s[j-1][i] == '*')
                    t2++;
            }
            if(s[n-1][i] == '*')
                t2++;
        }
        for(int i = 0; i < n; i++)
            for(int j = 0; j < m; j++)
                if(s[i][j] == '*')
                    mp[mx[i][j]][my[i][j]] = 1;
        int ans = 0;
        for(int i = 0; i < t1; i++)
        {
            memset(vis,0,sizeof(vis));
            ans += dfs(i);
        }
        printf("%d\n",ans);
    }
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值