最大匹配问题
题意:题目意思:
给定一个 n * m 的矩阵格子, 第二行给定一个k值表示池塘,接下来给出池塘坐标,要求的就是在不是池塘的区域用1 * 2 的小矩形填充它 ,问 最多能填充几个小矩形,并且打印出所有矩阵!
这题拿到手毫无头绪 是这个专题最难的一题了
这题值得多打几遍
#include<bits/stdc++.h>
using namespace std;
#define N 105
int mp[N][N];
int used[N];
int vis[N];
int n,m,r,c;
int dx[4]={0,1,0,-1};
int dy[4]={1,0,-1,0};
int flag[N][N];
int ans[N][2];
int cnt;
vector<int>g[N*N];
bool dfs(int x)
{
for(int j=0;j<g[x].size();j++)
{
if(!used[ g[x][j] ]) //所有的j都改为了g[x][j]
{
used[ g[x][j] ]=1;
if(!vis[ g[x][j] ]||dfs(vis[ g[x][j] ]))
{
vis[ g[x][j] ]=x;
return true;
}
}
}
return false;
}
int find1(void)
{ int ans=0;
memset(vis,0,sizeof(vis));
for(int i=1;i<=cnt-1;i++)
{
memset(used,0,sizeof(used));
if(dfs(i))ans++;
}
return ans;
}
bool inmap(int x,int y)
{
if(x>=1&&x<=n&&y>=1&&y<=m)return true;
else return false;
}
int main()
{
while(scanf("%d%d",&n,&m),n||m)
{
memset(mp,0,sizeof(mp));
memset(flag,0,sizeof(flag));
memset(ans,0,sizeof(ans));
for(int i=0;i<=N*N;i++)g[i].clear();
int q;
scanf("%d",&q);
while(q--)
{
int a,b;
scanf("%d%d",&a,&b);
mp[a][b]=1;
}
cnt=1;
for(int i=1;i<=n;i++)//扫描各个点 进行离散化
for(int j=1;j<=m;j++)
if(mp[i][j]==0)
{
ans[cnt][0]=i;
ans[cnt][1]=j;//这个数组用的巧妙!!
flag[i][j]=cnt++;//从小到大标记各个有效点
}
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
if(flag[i][j])
if( 1&(i+j) )//只处理奇数的 可以提高效率 否则的话 ans为两倍(匹配两次) 并且打印各个点就会出错!!很重要
{
for(int k=0;k<4;k++)//类似dfs 扫描一个点 将其匹配的点(就是相邻点)存入匹配向量!!!
{
int x=i+dx[k];
int y=j+dy[k];
if(inmap(x,y)&&flag[x][y])
g[ flag[i][j] ].push_back( flag[x][y] );
}
}
printf("%d\n",find1());
for(int i=1;i<cnt;i++)//使用vis数组来打印 !这时用上了之前所处理的记录数组
if(vis[i])
{
printf("(%d,%d)--(%d,%d)\n", ans[i][0],ans[i][1],ans[ vis[i] ][0],ans[ vis[i] ][1] );
}
printf("\n");
}
}
来源:https://www.cnblogs.com/bxd123/p/10372433.html