折半搜索+二分 Treasure Division hdu 3017

看到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;
}



你可能感兴趣的:(优化,搜索,ACM,折半搜索)