[SUMMER TRAIN] D1-B
題目位址 http://poj.org/problem?id=3977
題意: 輸入一個集合(n <= 35), 求出一子集使得此子集中所有元素的和的絕對值最小. 輸出和的絕對值與子集元素的數量.
- 無腦暴力O(2^n), 妥妥的t掉.
-
分成兩個子集 對每個子集暴力枚舉, 然後兩個子集進行比對.
時間複雜度 O((log2(n/2))^2 * 2^(n/2)) 比1e6 大了一點點, 可以接受.
- 坑點:
- long long
- fabs()
#include <stdio.h>
#include <map>
#include <algorithm>
using namespace std;
int n, cnt;
long long in[], sum;
const long long INF = ;
map <long long, int> fst;
map <long long, int> lst;
map <long long, int> :: iterator itf;
map <long long, int> :: iterator itl;
long long labs(long long a) {
return a >= ? a : -a;
}
int mmin(int a, int b) {
return a < b ? a : b;
}
long long mmin(long long a, long long b) {
return a < b ? a : b;
}
int main() {
// freopen("in.in", "r", stdin);
// freopen("b.out", "w", stdout);
while (scanf("%d", &n) == && n) {
fst.clear(), lst.clear();
sum = INF, cnt = ;
for (int i = ; i < n; ++i)
scanf("%lld", in+i);
sort(in, in+n);
long long ctmp = ((long long) << (int)(n/));
for (long long i = ; i < ctmp; ++i) {
long long tmp = ;
int tcnt = ;
for (int j = ; ; ++j) {
if (!(i >> j)) break;
if ((i >> j) & ) tmp += in[j], ++tcnt;
}
if (fst[tmp] == ) fst[tmp] = tcnt;
else fst[tmp] = fst[tmp] < tcnt ? fst[tmp] : tcnt;
if (labs(tmp) == sum) cnt = mmin(cnt, tcnt);
else if (labs(tmp) < sum) cnt = tcnt, sum = labs(tmp);
}
for (long long i = ctmp; i < ((long long)<<n); i += ctmp) {
long long tmp = ;
int tcnt = ;
for (int j = ; ; ++j) {
if (!(i>>j)) break;
if ((i>>j) & ) tmp += in[j], ++tcnt;
}
if (lst[tmp] == ) lst[tmp] = tcnt;
else lst[tmp] = lst[tmp] < tcnt ? lst[tmp] : tcnt;
if (labs(tmp) == sum) cnt = mmin(cnt, tcnt);
else if (labs(tmp) < sum) cnt = tcnt, sum = labs(tmp);
}
for (itl = lst.begin(); itl != lst.end(); ++itl) {
itf = fst.lower_bound(-(itl->first));
if (itf != fst.begin()) {
--itf;
if (labs(itf->first + itl->first) == sum)
cnt = mmin(itf->second + itl->second, cnt);
else if (labs(itf->first + itl->first) < sum) {
sum = labs(itf->first + itl->first);
cnt = itf->second + itl->second;
}
++itf;
}
if (itf == fst.end()) continue;
if (labs(itf->first + itl->first) == sum)
cnt = mmin(itf->second + itl->second, cnt);
else if (labs(itf->first + itl->first) < sum) {
sum = labs(itf->first + itl->first);
cnt = itf->second + itl->second;
}
}
printf ("%lld %d\n", sum, cnt);
}
return ;
}
/**********
**常數巨大**
***********/
- 變量名巨醜無比而且較為混亂.
- 初寫的時候沒有想到會寫這麼多行, 直接在主函數中進行處理, 可讀性–.
- 細節錯誤不斷.