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