| ||||||||||
| Online Judge | Problem Set | Authors | Online Contests | User | ||||||
|---|---|---|---|---|---|---|---|---|---|---|
| Web Board Home Page F.A.Qs Statistical Charts | Current Contest Past Contests Scheduled Contests Award Contest | |||||||||
折半枚举 写的不好看#include <cstdio>
#include <iostream>
#include <cmath>
#include <climits>
#include <algorithm>
using namespace std;
typedef long long ll;
#define MAXN 35
const int SETSIZE = 1 << 19;
int N;
pair<ll, int> halfset[SETSIZE];
//fist is value, second is id;
ll arr[MAXN];
ll ans = LLONG_MAX, acnt;
bool cmp(pair<ll, int> a, pair<ll, int> b){
if(a.first == b.first) return a.second < b.second;
return a.first < b.first;
}
ll mabs(ll x){
return x >= 0 ? x : -x;
}
void update(int pos, ll v, int c) {
ll temp = mabs((halfset[pos].first + v));
int ncnt = halfset[pos].second + c;
if (ans > temp || (ans == temp && ncnt < acnt)) {
ans = temp;
acnt = ncnt;
}
}
int main() {
int i, j;
while (scanf("%d", &N) == 1) {
if (N == 0)
break;
for (i = 0; i < N; i++)
scanf("%lld", &arr[i]);
//enumerate half of the set
int hn = N / 2;
for (i = 0; i < 1 << hn; i++) {
ll val = 0;
int cnt = 0;
for (j = 0; j < hn; j++) {
if ((i >> j) & 1) {
val += arr[j];
cnt++;
}
}
halfset[i] = make_pair(val, cnt);
}
sort(halfset, halfset + (1 << hn), cmp);
//deal with the left elements
ans = LLONG_MAX;
for (i = 0; i < 1 << (N - hn); i++) {
ll val = 0;
int cnt = 0;
for (j = 0; j < N - hn; j++) {
if ((i >> j) & 1) {
val += arr[j + hn];
cnt++;
}
}
int low = (lower_bound(halfset, halfset + (1 << hn), make_pair(-val, 0), cmp) - halfset);
//equal or bigger than it
if ((cnt + halfset[low].second) > 0)
update(low, val, cnt);
else if (low + 1 < (1 << hn))
update(low + 1, val, cnt);
int k;
//find the element small than it
if (low - 1 >= 0) {
for (k = low - 2; k >= 0 && halfset[k].first == halfset[low - 1].first && (halfset[k].second + cnt) > 0; k--);
k++;
if ((cnt + halfset[k].second) > 0)
update(k, val, cnt);
}
}
printf("%lld %d\n", ans, acnt);
}
return 0;
}
生成一半的数的集合
另一半再生成一个数二分查找 lowerbound找出大于等于负新生成数的位置low 然后更新 还要更新枚举集合里这个值稍小的数 即low - 1 当有很多个比它小的数的时候 找到元素总数最小的那一个 即low - k
Followed by: Post your reply here: |
All Rights Reserved 2003-2013 Ying Fuchen,Xu Pengcheng,Xie Di
Any problem, Please Contact Administrator