泥泞的地面
给定一些矩阵 要求矩阵的指定位置被宽度为1的长方形覆盖 长方形可以重叠 但是只能覆盖在指定位置 最少要多少个长方形
2要素: 要么被行覆盖 要么被列覆盖
所以行和列之间建立二分图即可
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <queue>
using namespace std;
const int N=55;
const int M=N*N;
int read()
{
int x=0,f=0,c=getchar();
while(c<'0'||c>'9'){if(c=='-')f=1;c=getchar();}
while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();}
return f?-x:x;
}
struct Edge
{
int to,next;
}e[M*2];
int head[M],cnt;
void add(int a,int b){ e[++cnt]=(Edge){b,head[a]}; head[a]=cnt;}
//void add(int a,int b){ _add(a,b); _add(b,a);}
bool mp[N][N];
int row[N][N],col[N][N],num;
bool vis[M];
int match[M];
int n,m;
bool dfs(int x)
{
for(int i=head[x];i;i=e[i].next)
{
int y=e[i].to;
if(vis[y]) continue; vis[y]=1;
if(!match[y]||dfs(match[y])){ match[y]=x; return true;}
}
return false;
}
int main()
{
n=read(); m=read();
for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++)
mp[i][j]=(getchar()=='*'?1:0);
getchar();
}
for(int j=1;j<=m;j++)
for(int i=1;i<=n;i++)
if(mp[i][j])
{
if(!mp[i-1][j]) num++;
col[i][j]=num;
}
num=0;
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
if(mp[i][j])
{
if(!mp[i][j-1]) num++;
row[i][j]=num;
}
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
if(mp[i][j]) add(row[i][j],col[i][j]);
int ans=0;
for(int i=1;i<=num;i++)
{
memset(vis,0,sizeof vis);
ans+=dfs(i);
}
printf("%d",ans);
return 0;
}

浙公网安备 33010602011771号