POJ-3020 Antenna Placement 最大独立集 | 状态压缩DP

  题目链接:http://poj.org/problem?id=3020

  大意就是,给你一张图,图中某些地方标记为‘*’,要你用1*2的圈覆盖所有的‘*',圈之间可以重叠,要求使得圈的数目最少。

  开始我想的是状态压缩DP,后来发现复杂度有点高,以为会TLE。看了Discuss才知道正解是用最大独立集做,即在图上构造一张二分图,然后相邻的’*‘建立边关系,求最大独立集就可以了。至于算法的正确性,我们把独立的点和与之相邻的未盖点看做一个圈就可以了,如果少了一个独立的点,那么’*‘就会覆盖不完全,所以最大独立集就是最少的圈数。

 1 //STATUS:G++_AC_0MS_908KB

 2 #include<stdio.h>

 3 #include<stdlib.h>

 4 #include<string.h>

 5 #include<math.h>

 6 #include<iostream>

 7 #include<string>

 8 #include<algorithm>

 9 #include<vector>

10 #include<queue>

11 #include<stack>

12 using namespace std;

13 #define LL __int64

14 #define pii pair<int,int>

15 #define Max(a,b) ((a)>(b)?(a):(b))

16 #define Min(a,b) ((a)<(b)?(a):(b))

17 #define mem(a,b) memset(a,b,sizeof(a))

18 #define lson l,mid,rt<<1

19 #define rson mid+1,r,rt<<1|1

20 const int N=50,INF=0x3f3f3f3f,MOD=1999997;

21 const LL LLNF=0x3f3f3f3f3f3f3f3fLL;

22 

23 char map[N][N];

24 int dx[4]={-1,0,1,0},dy[4]={0,1,0,-1};

25 int sx[N][N],sy[N][N],p[N*N],vis[N*N],y[N*N],g[210][210];

26 int T,n,m,nx,ny;

27 

28 void getg()

29 {

30     int i,j,t,q,x,y;

31     t=1;

32     for(i=nx=0;i<n;i++)

33         for(j=t=!t;j<m;j+=2)

34             if(map[i][j]=='*')sx[i][j]=nx++;

35     t=0;

36     for(i=ny=0;i<n;i++)

37         for(j=t=!t;j<m;j+=2)

38             if(map[i][j]=='*')sy[i][j]=ny++;

39     for(i=0;i<n;i++){

40         for(j=0;j<m;j++){

41             if(sx[i][j]!=-1){

42                 for(q=0;q<4;q++){

43                     x=i+dx[q];

44                     y=j+dy[q];

45                     if(x>=0&&x<n && y>=0&&y<m && sy[x][y]!=-1)

46                         g[sx[i][j]][sy[x][y]]=1;

47                 }

48             }

49         }

50     }

51 }

52 

53 int dfs(int x)

54 {

55     int v;

56     for(v=0;v<ny;v++){

57         if(g[x][v] && !vis[v]){

58             vis[v]=1;

59             if(p[v]==-1 || dfs(p[v])){

60                 p[v]=x;

61                 return 1;

62             }

63         }

64     }

65     return 0;

66 }

67 

68 int main()

69 {

70  //   freopen("in.txt","r",stdin);

71     int i,j,ans;

72     scanf("%d",&T);

73     while(T--)

74     {

75         ans=0;

76         mem(sx,-1);mem(sy,-1);

77         mem(p,-1);

78         mem(g,0);

79         scanf("%d%d",&n,&m);

80         for(i=0;i<n;i++)

81             scanf("%s",map[i]);

82 

83         getg();

84         for(i=0;i<nx;i++){

85             mem(vis,0);

86             if(dfs(i))ans++;

87         }

88 

89         printf("%d\n",nx+ny-ans);

90     }

91     return 0;

92 }

 

你可能感兴趣的:(ant)