Poj 3020 Antenna Placement

来源:互联网 发布:男士围巾知乎 编辑:程序博客网 时间:2024/05/22 06:52

题目大意:给定一个坐标图,图中每在一个点上覆盖就可在覆盖它上下左右4个点中任一个,问最少放几个。

思路:把每一个点都和与之相邻的4个点连边,就构成了一个二分图。利用匈牙利算法,最后输出的时候需要注意的是这里的点是所有可以放的点的两倍,而匹配数也是正常匹配数的二倍(A到B连了,B到A也连了),所以输出的时候应该先将匹配数除以2。

#include <iostream>using namespace std;#include <stdio.h>#include <memory.h>#include <string.h>const int SIZE = 520;int data[SIZE][SIZE];int matched[SIZE];int used[SIZE];char str[50][20];int n;int dfs(int m) {int i;for ( i=1;i<=n;i++ ) {if ( used[i]==0&&data[m][i]==1 ) {used[i]=1;if ( matched[i]==-1||dfs(matched[i]) ) {matched[i]=m;return 1;}}}return 0;}int Hungary() {int i,ctr;ctr=0;for ( i=1;i<=n;i++ ) {memset(used,0,sizeof(used));if ( dfs(i) )ctr++;}return ctr;}//初始化数据int initialization(int h,int w) {int ctr,i,j;int x,y;int s,d;ctr=0;for ( i=1;i<=h;i++ ) {for ( j=1;j<=w;j++ ) {if ( str[i][j]=='*' ) {ctr++;x=i;y=j;s=(x-1)*w+y;if ( y+1<=w&&str[x][y+1]=='*' ) {d=(x-1)*w+y+1;data[s][d]=1;//printf("%d %d\n",s,d);}if ( x+1<=h&&str[x+1][y]=='*' ) {d=(x)*w+y;data[s][d]=1;//printf("%d %d\n",s,d);}if ( y-1>=1&&str[x][y-1]=='*' ) {d=(x-1)*w+y-1;data[s][d]=1;//printf("%d %d\n",s,d);}if ( x-1>=1&&str[x-1][y]=='*' ) {d=(x-2)*w+y;data[s][d]=1;//printf("%d %d\n",s,d);}}}}//printf("%d\n",ctr);return ctr;}int main(){int result,i,t,h,w,j,temp;scanf("%d",&t);while (t--) {scanf("%d%d",&h,&w);getchar();memset(data,0,sizeof(data));memset(matched,-1,sizeof(matched));for ( i=1;i<=h;i++ ) {for ( j=1;j<=w;j++ ) {scanf("%c",&str[i][j]);}getchar();}temp=initialization(h,w);n=h*w;result=Hungary();printf("%d\n",temp-result/2);}return 0;}