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]; forint i = 1; i < n; i++ ) g = gcd( g, w[i] );
    
forint 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 ) );
    
forint 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();
      
forint 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(
000);
        
return answer;
    }
 
 
}


posted on 2007-07-20 20:20  woodfish  阅读(365)  评论(0编辑  收藏  举报

导航