Topcoder SRM 358:BalanceScale

现在有n件物品集合V,每件有一个重量Wi,现在要从里面选出一个集合S,使得V-S中的物品都能由S中的物品称出来,即在一个天平的的左边放入V-S中的1件物品,那么必定可以从S中选出一些物品(可以无限使用)放在右边,使得天平平衡。

现在要求集合S中元素个数的最小值。

现在,我们先求出Wi(i=1,2,3...n)的最大公倍数g,然后把每个Wi都除以g,这样gcd(Wi)=1,这样并不会影响最后的结果。现在证明如果V中的一个子集S的最大公倍数为1,那么V中的元素都可以有S中的元素称出来。
证明用的是 Bézout's identity定理。

那么现在的问题转换成从集合V中选出最小的集合S,使得集合S的公倍数于集合V的公倍数相同(同为1)。

设DP[x]为以x为最大公倍数的最小集合的个数,通过DP求解(其实就是BFS搜索),那么最后的结果就是DP[1]

int  d[ 10000100 ];
 
class  BalanceScale
{
  
public :
  
int  takeWeights(vector  < int >  w) 
  {
    
int  n  =  w.size();
    
int  g  =  w[ 0 ];  for int  i  =   1 ; i  <  n; i ++  ) g  =  gcd( g, w[i] );
    
for int  i  =   0 ; i  <  n; i ++  ) w[i]  /=  g;
    sort( w.begin(), w.end() );
    
if ( w[ 0 ==   1  )  return   1 ;
    
    queue
<   int   >  q;
    memset( d, 
1 , sizeof( d ) );
    
for int  i  =   0 ; i  <  n; i ++  ) { q.push( w[i] ); d[w[i]]  =   1 ; }
    
while ! q.empty()  &&  d[ 1 ==   0x01010101  )
    {
      
int  u  =  q.front(); q.pop();
      
for int  i  =   0 ; i  <  n; i ++  )
      {
        
int  v  =  gcd( u, w[i] );
        
if ( d[v]  ==   0x01010101  ) { d[v]  =  d[u]  +   1 ; q.push( v ); }
      }
    }
    
return  d[ 1 ];
  }
};

下面是DFS的代码:
import  java.util. * ;
 
public   class  BalanceScale {
    
int  gcd( int  x,  int  y) {
        
while  (y  !=   0 ) {
            
int  t  =  x  %  y; x  =  y; y  =  t;
        }
        
return  x;
    }
 
    
int [] w;
    
int  answer;
 
    
void  bt( int  i,  int  d,  int  c) {
        
if  (c  >=  answer) {
            
return ;
        }
        
if  (i  ==  w.length) {
            
if  (d  ==   1 ) {
                answer 
=  c;
            }
            
return ;
        }
        
int  d1  =  gcd(d, w[i]);
        
if  (d1  !=  d) {
            bt(i 
+   1 , d1, c  +   1 );
        }
        bt(i 
+   1 , d, c);
    }
 
    
public   int  takeWeights( int [] weight) {
        
int  d  =   0 ;
        
for  ( int  x : weight) {
            d 
=  gcd(d, x);
        }
        
for  ( int  i  =   0 ; i  <  weight.length; i ++ ) {
            weight[i] 
/=  d;
        }
 
        w 
=  weight;
 
        answer 
=  weight.length;
        bt(
0 0 0 );
        
return  answer;
    }
 
 
}


你可能感兴趣的:(topcoder)