POJ 2785 折半枚举

来源:互联网 发布:php strcasecmp 编辑:程序博客网 时间:2024/05/16 05:57
#include <cstdio>#include <iostream>#include <algorithm>#define LL long long using namespace std;int a[4][4005];int b[2][4005*4005];int main(){    int n;    while(cin >> n){        for(int i = 0;i < n;i++){            for(int j = 0;j < 4;j++){                scanf("%d",&a[j][i]);            }        }        int cnt1 = 0;        int cnt2 = 0;        for(int i = 0;i < n;i++){            for(int j = 0;j < n;j++){                b[0][cnt1++] = a[0][i] + a[1][j];            }        }        for(int i = 0;i < n;i++){            for(int j = 0;j < n;j++){                b[1][cnt2++] = a[2][i] + a[3][j];            }        }        sort(b[1],b[1]+cnt2);        LL ans = 0;        for(int i = 0;i < cnt1;i++){            ans += upper_bound(b[1],b[1]+cnt2,0-b[0][i]) - lower_bound(b[1],b[1]+cnt2,0-b[0][i]);        }        cout << ans << endl;    }    return 0;}

折半枚举就是讲原先整体的枚举分成部分枚举,然后再两个部分中利用符合条件的枚举的性质进行优化的
本来想了个用母函数做的,但是做完之后发现超时了;
这样想法本身并没有错误但是这里面会有一个母函数本质的问题,母函数的本质是将所有的序列都生成这时候其实就是相当于穷举了,但是这里面只考虑了0的系数所以这时候母函数就会生成太多的累赘的序列了,所以采用母函数是会超时的。下面是用母函数做的

#include <cstdio>#include <iostream>#include <algorithm>#include <queue>#include <cmath>#include <cstring>#include <stack>#include <set>#include <map>#include <vector>using namespace std;#define INF 0x2fffffff#define LL long long#define MAX(a,b) ((a)>(b))?(a):(b)#define MIN(a,b) ((a)<(b))?(a):(b)int a[4][4005];int main(){    int t;    int n;    while(scanf("%d",&n)!=EOF){        for(int i = 0;i < n;i++){            for(int j = 0;j < 4;j++){                scanf("%d",&a[j][i]);            }        }        map<int,int> ma;        queue<pair<int,int> > que;        for(int i = 0;i < n;i++){            que.push(make_pair(a[0][i],1));        }        for(int i = 1;i < 4;i++){            for(int j = 0;j < n;j++){                int si = que.size();                for(int k = 0;k < si;k++){                    pair<int,int> c = que.front();                    que.pop();                    que.push(c);                    c.first = a[i][j] + c.first;                    if(ma.find(c.first) == ma.end()){                        ma[c.first] = 0;                    }                    ma[c.first] += c.second;                }             }            while(!que.empty()) que.pop();            for(map<int,int>::iterator ite = ma.begin();ite != ma.end();ite++){                que.push(make_pair(ite->first,ite->second));            }            if(i != 3)                ma.clear();        }        if(ma.find(0) != ma.end())            printf("%d\n",ma[0]);        else            printf("%d\n",0);    }     return 0;}
0 0