【codevs 1022】覆盖(匈牙利算法)

来源:互联网 发布:javascript复选框全选 编辑:程序博客网 时间:2024/06/11 15:48

1022 覆盖

 时间限制: 1 s  空间限制: 128000 KB 题目等级 : 大师 Master

题目描述 Description

    有一个N×M的单位方格中,其中有些方格是水塘,其他方格是陆地。如果要用1×2的矩阵区覆盖(覆盖过程不容许有任何部分重叠)这个陆地,那么最多可以覆盖多少陆地面积。

输入描述 Input Description

    输入文件的第一行是两个整数N、M(1<=N,M<=100),第二行为一个整数K( K<=50),接下来的K行,每行两个整数X,Y表示K个水塘的行列位置。(1<=X<=N,1<=Y<=M)。 

输出描述 Output Description

    输出所覆盖的最大面积块(1×2面积算一块)。

样例输入 Sample Input

    4 4

    6

    1 1

    1 4

    2 2

    4 1

    4 2

    4 4

样例输出 Sample Output

    4

 【题解】【匈牙利算法】

【将可能被一起覆盖的方格之间连边,构成一个二分图,用dfs求出一边的点(类似于上一道题),然后跑匈牙利算法】

#include<cstdio>#include<cstring>#include<algorithm>using namespace std;int d[4][2]={{-1,0},{1,0},{0,-1},{0,1}};int a[20010],nxt[20010],p[10010],tot;int mp[110][110],f[10010],opt[10010];int n,m,k,tt,ans;bool ch[110][110],vis[10010];inline void add(int x,int y){tot++; a[tot]=y; nxt[tot]=p[x]; p[x]=tot;}bool dfs(int x){for(int i=p[x];i!=-1;i=nxt[i]) if(!vis[a[i]])  {  vis[a[i]]=1;  if(f[a[i]]==-1||dfs(f[a[i]]))   {   f[a[i]]=x;   return 1;   }  }return 0;}void type(int x,int t){vis[x]=1; opt[x]=t;for(int i=p[x];i!=-1;i=nxt[i]) if(!vis[a[i]]) type(a[i],t^1);}int main(){int i,j;memset(p,-1,sizeof(p));memset(f,-1,sizeof(f));memset(opt,-1,sizeof(opt));memset(nxt,-1,sizeof(nxt));scanf("%d%d%d",&n,&m,&k);for(i=1;i<=k;++i) { int x,y; scanf("%d%d",&x,&y); ch[x][y]=1; }for(i=1;i<=n;++i) for(j=1;j<=m;++j)  if(!ch[i][j]) mp[i][j]=++tt;for(i=1;i<=n;++i) for(j=1;j<=m;++j)  if(!ch[i][j])   {       int x=i,y=j;       for(int l=0;l<4;++l)        {        int xx=x+d[l][0],yy=y+d[l][1];        if(xx>0&&xx<=n&&yy>0&&yy<=m&&!ch[xx][yy])         add(mp[x][y],mp[xx][yy]);}    }for(i=1;i<=tt;++i) if(!vis[i]) type(i,0);for(i=1;i<=tt;++i) if(!opt[i])  { memset(vis,0,sizeof(vis)); if(dfs(i)) ans++;   }  printf("%d\n",ans);return 0;}

0 0
原创粉丝点击