泥泞的地面

给定一些矩阵 要求矩阵的指定位置被宽度为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;
}
posted @ 2022-02-11 21:15  __iostream  阅读(118)  评论(0)    收藏  举报