POJ 3977 折半枚举+二分搜索
2017-08-15 00:00
417 查看
#include <iostream> #include <algorithm> #include <string.h> #include <stdio.h> #include <math.h> #include <vector> #include <map> using namespace std; #define N 45 #define PI 4 * atan(1.0) #define mod 1000000007 #define met(a, b) memset(a, b, sizeof( a )) #define INF 10000000000000000 typedef long long LL; int n; LL a ; LL Abs(LL x){ return x < 0 ? -x : x; } int main(){ while(scanf("%d", &n), n){ for(int i = 0 ; i < n ; i++) scanf("%I64d", &a[i]); map<LL, int> M; map<LL, int>::iterator it; pair<LL, int> ans(Abs(a[0]), 1); for(int i = 1 ; i < 1 << ( n / 2 ) ; i++){ LL sum = 0; int cnt = 0; for(int j = 0 ; j < ( n / 2 ) ; j++){ if(( i >> j ) & 1){ sum += a[j]; cnt++; } } ans = min(ans, make_pair(Abs(sum), cnt));//全部是前半部分的; if(M[sum]) //更新cnt为小的; M[sum] = min(M[sum], cnt); else M[sum] = cnt; } for(int i = 1 ; i < 1 << ( n - n / 2 ) ; i++){ LL sum = 0; int cnt = 0; for(int j = 0 ; j < ( n - n / 2 ) ; j++){ if(( i >> j ) & 1){ sum += a[j + n / 2]; cnt++; } } ans = min(ans, make_pair(Abs(sum), cnt));///全部是后半部分的; it = M.lower_bound(-sum);///找到第一个大于-sum的位置,然后取两种情况的最小值; if(it != M.end()) ans = min(ans, make_pair(Abs(sum + it->first), cnt + it->second)); if(it != M.begin()){ it--; ans = min(ans, make_pair(Abs(sum + it->first), cnt + it->second)); } } printf("%I64d %d\n", ans.first, ans.second); } return 0; }
相关文章推荐
- poj 3977 折半枚举二分搜索
- POJ 3977:Subset(折半枚举+二分)
- POJ 3977 Subset(二分+折半枚举)
- POJ 3977 Subset (折半枚举+二分)
- POJ-3977-折半枚举,二分
- POJ 3977 Subset(折半枚举 + 二分查找)
- POJ 3977 Subset (简单折半枚举)
- poj 3977 折半枚举+二进制枚举+二分
- POJ - 3977 Subset(折半枚举)
- POJ 2785 4 Values whose Sum is 0 折半枚举(双向搜索)
- POJ 2785 4 Values whose Sum is 0(二分+折半枚举)
- POJ 3977 Subset | 折半搜索
- 【折半枚举 && 二分】POJ - 2785 4 Values whose Sum is 0
- 【POJ 2785 4 Values whose Sum is 0】+ 折半枚举(双项搜索))
- [poj] 3977 Subset || 折半搜索MITM
- POJ 3977(枚举+二分)
- 160_折半枚举(双向搜索) 4 Values whose sum is 0 (POJ No.2785)
- POJ 2785 4 Values whose Sum is 0【双向搜索/折半枚举】
- POJ 3977 Subset (折半枚举)
- poj 1054 The Troublesome Frog 枚举+二分搜索