优化C ++代码

时间:2013-02-18 08:55:46

标签: c++ optimization

我正在尝试在线评判的经典子集和问题。然而,这次的差异是n <= 30,因此最大操作可以达到30 * 2 ^ 30。我已经有了一些工作代码。但是,程序的时间限制是1秒,我的程序在0.5到1.1秒之间徘徊。这导致了TLE,尽管我尽力加快我的代码速度。你们有什么提示我可以如何进一步加快和优化我的代码吗?提前致谢。

#include <iostream>
#include <cstdio>
using namespace std;

unsigned power(unsigned x, unsigned y){        //pow function
    unsigned sum=x;
    for (int i=1;i<=y-1;i++)
        sum*=x;
    return sum;
}

int main(){
    unsigned t, n, p, sum, sum2, tmpsum=0;
    unsigned bars[32];
    bool found;
    scanf("%u", &t);
    while (t--){
        tmpsum=0;
        found=false;
        scanf("%u %u", &n, &p);
        for (int i=0;i<p;i++){
            scanf("%u",&bars[i]);
            tmpsum+=bars[i];
        }
        if (tmpsum<n)found=false;
        unsigned end=power(2,p)-1;          //counting from the end and from the start
        for (unsigned i=0;i<power(2,p)&&tmpsum>=n;i++){       //counting from 1 to 2^n in binary
            sum=0;
            sum2=0;
            for (unsigned j=0;j<p;j++){
                if (i&(1<<j))
                    sum+=bars[j];
                if (end&(1<<j))     //counting from the end and start at the same time
                    {sum2+=bars[j];end--;}
            }
            if (sum==n||sum2==n)
                {found=true;break;}
        }
        cout<<(found==true?"YES":"NO")<<endl;
    }
}

7 个答案:

答案 0 :(得分:3)

power(2,p)移出循环。

for (unsigned i=0;i<power(2,p)&&tmpsum>=n;i++)
                      ^^^^

答案 1 :(得分:3)

使用位移计算两度。

答案 2 :(得分:2)

编写丑陋的代码并不会使代码更快,将语句分成不同的行,即用

替换{sum2+=bars[j];end--;}
{
    sum2 += bars[j];
    --end;
}

关于这个问题:你的主要时间损失可能在这里:

for (unsigned i=0;i<power(2,p)&&tmpsum>=n;i++){

除非你有一个特别好的编译器,否则在循环的每个循环中计算power(2, p)一次,这是完全不需要的。预先计算它。

int pow2p = power(2, p);
for (unsigned i=0;i<pow2p&&tmpsum>=n;i++){

此外,以这种方式执行2的功能非常慢,因此请改用<<1<<p == power(2, p))。

修改由于这已被接受,我会从其他答案/评论中收集一些小点:

  1. 正如Nim指出的那样,tmpsum>=n检查不需要在每个循环中完成,因为ntmpsum在循环期间都不会发生变化。

    < / LI>
  2. 正如Karthik T指出的那样,if (tmpsum<n)found=false;行是多余的,此时found永远不会是false

答案 3 :(得分:1)

除了别人所说的,Avoid Branching。 例如:

if (i&(1<<j))
    sum+=bars[j];

可以写成

sum+=bars[j] * ((i&(1<<j))>>j);

当然,它使得阅读代码变得更加难以阅读。

答案 4 :(得分:0)

if (tmpsum<n)found=false;

此行无效,found已经false

1<<j

正在计算两次,可以通过存储结果减少到一次。

答案 5 :(得分:0)

对于初学者,您可以将power(2,p)移出for循环

for (unsigned i=0, end=power(2,p); i<end && tmpsum>=n; i++)

答案 6 :(得分:-1)

  1. 功率(2,p)等于1 <&lt; P
  2. 将sum和sum2定义为寄存器变量。

    注册无符号和,sum2;