看到10^30 就要想到折半搜索啊==
大致的思路就是
枚举前n/2的情况
枚举后n/2的情况
然后对于前n/2的情况在后n/2的中进行二分查找 复杂度就解决辣!
搜索新姿势get!!!!!!:
代码如下:
/* ^^ ====== ^^
ID: meixiuxiu
PROG: test
LANG: C++11
*/
#include <cstdio>
#include <cstdlib>
#include <iostream>
#include <algorithm>
#include <cstring>
#include <climits>
#include <string>
#include <vector>
#include <cmath>
#include <stack>
#include <queue>
#include <set>
#include <map>
#include <sstream>
#include <cctype>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int ,int> pii;
#define MEM(a,b) memset(a,b,sizeof a)
#define CLR(a) memset(a,0,sizeof a);
#define pi acos(-1.0)
#define maxn 40000
#define maxv 100005
const int inf = 0x3f3f3f3f;
const int MOD = 1e9 + 7;
vector<int> s1[31][31],s2[31][31];
ll a[35];
int main()
{
//freopen("in.txt","r",stdin);
int n;
while(cin >> n){
// cout << n << endl;
for(int i=0;i<=30;i++){
for(int j=0;j<=30;j++){
s1[i][j].clear();
s2[i][j].clear();
}
}
for(int i=0;i<n;i++){
scanf("%lld",&a[i]);
}
int mid = (n/2);
for(int i=0;i<(1<<mid);i++){
ll tot = 0;
int cnt1 = 0;
int cnt2 = 0;
for(int j=0;j<mid;j++){
if(i&(1<<j)){
tot+=a[j];
cnt1++;
}
else tot -= a[j],cnt2++;
}
s1[cnt1][cnt2].push_back(tot);
}
for(int i=0;i<=mid;i++){
for(int j=0;j<=mid;j++){
sort(s1[i][j].begin(),s1[i][j].end());
}
}
int mid1 = (n-mid);
for(int i=0;i<(1<<mid1);i++){
ll tot = 0;
int cnt1 = 0;
int cnt2 = 0;
for(int j=0;j<mid1;j++){
if(i&(1<<j)){
tot += a[j+mid];
cnt1++;
}
else tot -= a[j+mid], cnt2++;
}
s2[cnt1][cnt2].push_back(tot);
}
for(int i=0;i<=mid1;i++){
for(int j=0;j<=mid1;j++){
sort(s2[i][j].begin(),s2[i][j].end());
}
}
ll nmin = inf;
for(int i=0;i<=mid;i++){
for(int j=0;j<=mid;j++){
int s = s1[i][j].size();
for(int k=0;k<s;k++){
ll t = s1[i][j][k];
//cout << fabs(t) << endl;
if(i+j==n)nmin = min((ll)fabs(t),nmin);
int m1 = (n/2),m2 = (n-n/2);
int pos,siz;
if(i<=m1 && j<=m2 && s2[m1-1][m2-1].size()){
pos = lower_bound(s2[m1-i][m2-j].begin(),s2[m1-i][m2-j].end(),-1*t)-s2[m1-i][m2-j].begin();
siz = s2[m1-i][m2-j].size();
if(pos < siz && pos >= 0){
nmin = min(nmin,(ll)fabs(t+s2[m1-i][m2-j][pos]));
}
if(pos-1 < siz && pos-1 >=0){
nmin = min(nmin,(ll)fabs(t+s2[m1-i][m2-j][pos-1]));
}
if(pos+1 < siz && pos+1 >=0){
nmin = min(nmin,(ll)fabs(t+s2[m1-i][m2-j][pos+1]));
}
}
swap(m1,m2);
if(i<=m1 && j<=m2 && s2[m1-i][m2-j].size()){
pos = lower_bound(s2[m1-i][m2-j].begin(),s2[m1-i][m2-j].end(),-1*t)-s2[m1-i][m2-j].begin();
siz = s2[m1-i][m2-j].size();
if(pos < siz && pos >= 0){
nmin = min(nmin,(ll)fabs(t+s2[m1-i][m2-j][pos]));
}
if(pos-1 < siz && pos-1 >=0){
nmin = min(nmin,(ll)fabs(t+s2[m1-i][m2-j][pos-1]));
}
if(pos+1 < siz && pos+1 >=0){
nmin = min(nmin,(ll)fabs(t+s2[m1-i][m2-j][pos+1]));
}
}
}
}
}
printf("%lld\n",nmin);
}
return 0;
}