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;
}

 

 

posted @ 2012-07-05 18:55  wutaoKeen  阅读(141)  评论(0编辑  收藏  举报