[Usaco2005 Jan]Muddy Fields泥泞的牧场

Description

雨连续不断的击打了放牛的牧场,一个R行C列的格子(1 <= R <= 50,
1 <= C <= 50)。虽然这对草来说是件好事,但这却使得一些没有草遮盖的土地
变得很泥泞。牛们是很小心的食草动物;他们不想在吃草时把蹄子弄脏。
为了避免它们把蹄子弄脏,农夫约翰要在那些泥泞的地方铺上木板子。每个1个
单位宽,长度任意。每个板子都必须放到与牧场一边平行。
农夫约翰希望用最少的板子来覆盖泥泞的部分。一些地方可能需要多于一块板
子来覆盖。木板不可以遮住草地,剥夺牛吃草的地方,但是他们可以相互重叠。
计算最少需要多少块板子来覆盖所有的泥地。

Input

* 第一行:两个整数R和C,由空格隔开。
* 第2到第R+1行:每行为一个长度为C的字符串。'*'代表泥地,'.'代表草地。
无空格。

Output

* 第一行:一个整数,其值为最少需要的板子数目

Sample Input

4 4
*.*.
.***
***.
..*.

Sample Output

4
输出细节:
板子 1, 2, 3 和 4 是这样摆放的:
1.2.
.333
444.
..2.
板子2与3,4重叠。


思路

这题因为板子可以连续盖,并且可以相互重叠,
所以我们可以将可以连续盖的板子打上编号
如样例:
行编号:
1 0 2 0
0 3 3 3
4 4 4 0
0 0 5 0
列编号:
1 0 2 0
0 3 2 4
5 3 2 0
0 0 2 0
这样每一个点就有了可以覆盖的板子选择
如:
(1,1)可以选择横着编号为1的板子,或竖着编号为1的板子//这两个好像没啥区别
(3,4)可以选择横着编号为5的板子,或竖着编号为2的板子

然后将每一个可以覆盖的点,与他可以选择的板子连边,
这样题目就转换成了最小点覆盖集;

代码
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
inline ll read()
{
    ll a=0,f=1; char c=getchar();
    while (c<'0'||c>'9') {if (c=='-') f=-1; c=getchar();}
    while (c>='0'&&c<='9') {a=a*10+c-'0'; c=getchar();}
    return a*f;
}
ll s,n,m,num;
ll aa[10001],f[10001],head[20001];
ll map1[101][101],map2[101][101],map3[101][101];
struct suffix
{
    ll to,stb;
}a[20001];
inline void insert(ll x,ll y)//前向星储存
{
    s++;
    a[s].to=y;
    a[s].stb=head[x];
    head[x]=s;
}
inline ll dfs(ll x)
{
    for(ll i=head[x];i;i=a[i].stb)
    {
        ll xx=a[i].to;
        if(f[xx]==num)
            continue;
        f[xx]=num;
        if(!aa[xx]||dfs(aa[xx]))
        {
            aa[xx]=x;
            return true;
        }
    }
    return false;
}
inline ll findout()
{
    ll sum=0;num=0;
    for(ll i=1;i<=n*m;i++)
    {
        num++;//一点点优化,不需要memset了
        if(dfs(i))
            sum++;
    }
    return sum;
}
int main()
{
    n=read();m=read();
    for(ll i=1;i<=n;i++)
    for(ll j=1;j<=m;j++)
    {
        char x;
        cin>>x;
        if(x=='*')
            map1[i][j]=1;
        else if(x=='.')
            map1[i][j]=0;
    }
    ll t=0,tt=0;
    for(ll i=1;i<=n;i++)
    for(ll j=1;j<=m;j++)//计算每个板子的编号
    {
        if(map1[i][j])
        {
            if(j>1&&map1[i][j-1])
                map2[i][j]=map2[i][j-1];
            else
                map2[i][j]=++t;
            if(i>1&&map1[i-1][j])
                map3[i][j]=map3[i-1][j];
            else
                map3[i][j]=++tt;
        }
    }
    /*for(ll i=1;i<=n;i++){
    for(ll j=1;j<=m;j++)
        cout<<map2[i][j];
    cout<<endl;}*/
    for(ll i=1;i<=n;i++)
    for(ll j=1;j<=m;j++)
    if(map1[i][j])
        insert(map2[i][j],map3[i][j]); 
    ll ans=findout();
    printf("%lld",ans);
    return 0;
}
 
 

原文地址:https://www.cnblogs.com/wzx-RS-STHN/p/12901983.html