poj 3020 Antenna Placement

这个题用到了黑白染色法:

黑白染色法

1

0

1

1

1

1

0

0

1

又是一个图,要求是把方格里的所有的1改为零,一次最多只能修改相邻的两个,为最少需要修改几次? 有是一个求最值得问题,但是似乎用于求最值的算法(贪心,动态规划……)都派不上用场,既然在这里提出,那么他肯定能用二分图最大匹配解决,关键是如何建图?

既然是每次只能拿相邻的两个,是两个,正好我们匹配的时候也是找两个进行匹配,这是否就是这个题和最大二分图匹配相联系的地方呢?  对 就是这里。但是每个点能和他四周的四个点匹配,那么我们怎么把所有的点分成来那个部分呢?   对  就是要把第i个点放到第一部分,第I个点周围的四个点放到第二部分,再把这四个点周围的16点放到第1部分

有了这样的思想,我们只需对原图做这样的改动:黑白染色使四周和中间的颜色不同。

 

1

5

2

3

4

6

图中黑白的意思是就是把点分类,图里的1,2,3,4,5,6表示的就是上面那个0,1图的1的个数

然后建图,把相邻的点相连,比如说12   2。。。。。。。

白色       黑色

  1         

3           2

5         4

6

然后要把所有一改为零,也就是要对每个点都操作,每个点都要有,那不就是最小顶点覆盖吗?对,这个问题有解决了。

View Code
View Code 

#include<iostream>

#include<cstdio>

#include<cstdlib>

#include<algorithm>

#include<cmath>

#include<queue>

#include<set>

#include<cstring>

#include<vector>

using namespace std;

bool G[425][425],visit[425];

int d[4][2] = { 0,1,1,0,0,-1,-1,0 },match[524];

void Get_G( int h , int  w ,int map[][15] )

{

  for( int i = 1; i <= h ; i++ )

   {     

         for( int j = 1 ; j <= w; j++ )

       {    

          if( map[i][j]!=0 && ( i +j )%2==1  )

          {

               for( int k = 0 ; k < 4 ; k ++ )

              {

                 int dx = d[k][0] + i ,dy = d[k][1] + j;

                 if( map[dx][dy]!=0 )

                 {

            //     printf( "%d %d\n",map[i][j],map[dx][dy] );

                  G[map[i][j]][map[dx][dy]] = 1;        

                 }        

              }        

          }        

       }        

    }        

}

bool path( int num , int N )

{

     for( int i = 1 ; i <= N ; i++ )

     {

         if( !visit[i] && G[num][i] )

         {

             visit[i] = true;

             if( match[i]==0 || path( match[i] , N ) )

             {

                 match[i] = num;

                 return true;        

             }        

         }        

     }    

     return false;

}

int main(  )

{

    int N,h,w,map[45][15];

    char str[15];

    while( scanf( "%d" ,&N )==1 )

    {

        while( N -- )

        {

           int count = 0;

           memset( G, 0 ,sizeof( G ) );

           memset( match , 0 , sizeof( match ) );

           memset( map , 0, sizeof( map ) );

           scanf( "%d %d",&h,&w );

           for( int i = 1 ; i <= h ; i ++ )

           {

                scanf( "%s",str + 1 );

                for( int j = 1 ; j <= w ; j ++ )

                {

                    if( str[j]=='*' ) map[i][j] = ++count;

                    else map[i][j] = 0;

                }        

           }

           Get_G( h , w ,map );

           int ans = 0;

           for( int i = 1 ; i<= count; i ++ )

           {

              memset( visit , 0 , sizeof( visit ) );

              if( path( i , count ) )

                  ans++;

           }

           printf( "%d\n",count - ans );

        }     

    }

    //system( "pause" );

    return 0;

}

 

 

你可能感兴趣的:(ant)