为什么这段代码更快?

时间:2013-03-05 11:49:06

标签: c++ optimization

这个问题让我疯了。顶部的代码在我的计算机上执行大约0.3秒,而底部的代码执行大约2.7秒。但是,我试图将第二个代码调整为尽可能与第一个代码类似,但它似乎总是更慢。谁能告诉我为什么第一个代码的执行速度比第二个代码快得多?

更快的代码

#include <cstdio>
#include <set>
#define ls(x) (x & (-x))
using namespace std;
int tc, n;
set<long long> s;
long long p, a[35];
int main () {
    freopen("mini3b.in","r",stdin);
    scanf("%d", &tc);
    while (tc--) {
        s.clear();
        scanf("%lld%d", &p, &n);
        for (int i = 0; i < n; ++i) scanf("%lld", &a[i]);
        int h = n/2;
        for (int i = 0; i < (1<<h); ++i) {
            long long sum = 0;
            for (int j = 0; j < h; ++j) if (i&(1<<j)) sum += a[j];
            s.insert(sum);
        }
        bool found = false;
        for (int i = 0; (i < (1<<(n-h))) && !found; ++i) {
            long long sum = 0;
            for (int j = 0; j < n-h; ++j) if (i&(1<<j)) sum += a[h+j];
            if (s.find(p-sum) != s.end()) found = true;
        }
        printf(found? "YES\n":"NO\n");
    }
}

SLOWER CODE

#include <cstdio>
#include <set>
using namespace std;
long long n, bars[35];
int t, p;
set<long long> s;
int main(){
    freopen("mini3b.in","r", stdin);
    scanf("%d", &t);
    while (t--){
        s.clear();
        scanf("%lld%d", &n, &p);
        for (int i=0;i<p;++i) scanf("%lld", &bars[i]);
        int limit=p/2;
        for (int i=0;i<(1<<limit);++i){
            long long sum=0;
            for (int j=0;j<limit;++j) if (i&(1<<j)) sum+=bars[j];
            s.insert(sum);
        }
        bool found=false;
        for (int i=0;i<(1<<(n-limit))&&!found;++i){
            long long sum=0;
            for (int j=0;j<p-limit;++j) if (i&(1<<j)) sum+=bars[limit+j];
            if (s.find(n-sum) != s.end()) 
                found=true;
        }
        printf(found?"YES\n":"NO\n");
    }
}

1 个答案:

答案 0 :(得分:3)

在第4个for循环中你有

for (int i = 0; (i < (1<<(n-h))) && !found; ++i) { // fast one
                          ^

针对

for (int i=0;i<(1<<(n-limit))&&!found;++i){ // slow one
                    ^

请注意,快速代码中的“n”是慢代码中的“p”。所以你应该

for (int i=0;i<(1<<(p-limit))&&!found;++i){ // slow one
                    ^