POJ 3977 Subset (折半枚舉+二分)__技巧性題

來源:互聯網
上載者:User

題目連結:http://poj.org/problem?id=3977


題意:給你n個數,求出這n個數的一個非空子集,使子集中的數加和的絕對值最小,在此基礎上子集中元素的個數應最小。


思路:n為35,直接枚舉的複雜度肯定是容不下的。但我們可以把這些數分為兩半,算出前一半元素所有子集對應的權和及個數,對後一半元素的每個子集,設其元素之和為sum,用二分尋找的方法在前一半中找元素和最接近-sum的子集即可。


#include<map>#include<cstdio>#include<cstring>#include<iostream>#include<algorithm>using namespace std;typedef long long ll;typedef pair<ll, ll> P;map<ll, int> mp;ll a[50];ll Abs(ll x) {  return x < 0 ? -x : x;}bool input(int& n) {  cin >> n;  if(n == 0) return false;  for(int i = 0; i < n; i++) cin >> a[i];  mp.clear();  return true;}void solve(int n) {  P ans = P(Abs(a[0]), 1);  map<ll, int> :: iterator it;  int mid = n >> 1;  //枚舉前半部分  for(int i = 0; i < 1<<mid; i++) {    ll sum = 0; int num = 0;    for(int j = 0; j < mid; j++) if(i >> j & 1) {      sum += a[j]; ++num;    }    if(num == 0) continue;    ans = min(ans, P(Abs(sum), num)); //全在前半段    // 插入map    it = mp.find(sum);    if(it != mp.end()) it->second = min(it->second, num);    else mp[sum] = num;  }  //枚舉後半部分  for(int i = 0; i < 1<<(n-mid); i++) {    ll sum = 0; int num = 0;    for(int j = 0; j < n-mid; j++) if(i >> j & 1) {      sum += a[j+mid]; ++num;    }    if(num == 0) continue;    ans = min(ans, P(Abs(sum), num)); //全在後半段    //在map中尋找答案    it = mp.lower_bound(-sum); //使這兩半的和的絕對值最小,前半段要盡量接近-sum    if(it != mp.end()) ans = min(ans, P(Abs(sum + it->first), it->second + num));    if(it != mp.begin()) --it, ans = min(ans, P(Abs(sum + it->first), it->second + num));  }  //輸出答案  cout << ans.first << ' ' << ans.second << endl;}int main() {  int n;  while(input(n)) {    solve(n);  }  return 0;}


聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.