poj-3977 Subset

呂振麒 bio photo By 呂振麒 Comment

傳送門:

Subset

code:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
#define abs(x) ((x)<0 ? (-(x)) : (x) )
typedef pair<ll, int> li;     // sum, size
li operator+ (const li &x, const li &y){
  li res = MP(x.X + y.X, x.Y + y.Y);
  return res;
}

int N, cnt;
ll arr[40], sum;
map<ll, int> part1, part2;
typedef map<ll, int>::iterator Iter;
li ans;

void cal_part(ll arr[], int sz, map<ll, int> &part){

  for(int i=1 ; i<1<<sz ; i++){
    sum = cnt = 0;
    for(int j=0 ; j<sz ; j++) if(i&(1<<j)){
      ++ cnt;
      sum += arr[j];
    }
    int &ori_size = part[sum];
    if(ori_size == 0 || ori_size > cnt ) 
      ori_size = cnt;
  }
}

inline void maintain_ans(li x){
  x.X = abs(x.X);
  ans = min(ans, x);
}

void init(){
  for(int i=0;i<N;i++) arr[i] = getint();
  part1.clear();
  part2.clear();
}

void sol(){
  if(N == 1){     // poor special case
    ans = MP(abs(arr[0]), 1);
    return;
  }
  cal_part ( arr, N>>1, part1 );
  cal_part ( arr+(N>>1), N - (N>>1), part2 );

  ans = MP(abs(sum), cnt);   // 拿最後一個當作初始答案
  
  Iter iter1 = part1.upper_bound(0), iter2 = part2.upper_bound(0);

  if(iter1 != part1.end() ) maintain_ans(*iter1);
  if(iter1 != part1.begin() ) maintain_ans(*(--iter1));

  if(iter2 != part2.end() ) maintain_ans(*iter2);
  if(iter2 != part2.begin() ) maintain_ans(*(--iter2));

  for(iter1 = part1.begin() ; iter1 != part1.end() ; ++iter1){
    iter2 = part2.upper_bound( -(*iter1).X );
    if(iter2 != part2.end() ) maintain_ans(*iter1 + *iter2);
    if(iter2 != part2.begin() ) maintain_ans(*iter1 + *(--iter2));
  }

}

inline void prin(){
  cout << ans.X << " " << ans.Y << endl;
}

int main(){
  while(cin >> N && N ){
    init();
    sol();
    prin();
  }
}
comments powered by Disqus