-1

我试图完成一个 UVa 问题:11559 - 活动策划。但是,我发现了一些让我感到困惑的事情。我已经编写了一个使用 printf 和 scanf 作为 IO 的代码,但是我在判断中得到了“超出时间限制”。我使用 cin 和 cout 更改了我的代码,然后我得到了“接受”。cin 或 cout 不比 scanf 和 printf 慢吗?这是我的代码。

“stdio.h”版本

#define inf 500000000

using namespace std;

int N, B, H, W;
int main ()
{
    while(scanf("%d %d %d %d", &N, &B, &H, &W)){
        int cost = inf;
        for(int i = 0; i < H; i++){
            int P, k ;
            scanf("%d",&P);
            for(int j = 0; j < W; j++){
                scanf("%d",&k);
                if(k >= N && N*P < cost) cost = N*P;
            }
        }
        if(cost <= B) printf("%d\n",cost);
        else{
            printf("stay home\n");
        }
    }
    return 0;

}

“iostream”版本

#define inf 500000000

using namespace std;

int N, B, H, W;
int main ()
{
    while(!cin.eof()){
        int cost = inf;
        cin >> N >> B >> H >> W;
        if(cin.eof()) break;
        for(int i = 0; i < H; i++){
            int P, k ;
            cin >> P;
            for(int j = 0; j < W; j++){
                cin >> k;
                if(k >= N && N*P < cost) cost = N*P;
            }
        }
        if(cost <= B) cout << cost << endl;
        else{
            cout << "stay home" << endl;
        }
    }
    return 0;
}
4

3 回答 3

4

不,cin并且cout与使用printf/没有显着不同scanf。但是,endlwill call ofstream::flush(),这将与 相同printf("%d\n", cost); fflush(stdout);,我希望如果你这样做,它也会在那里运行得更慢。

cin此外,混合scanf或类似会增加更多时间,因为代码必须一直“同步”两个 I/O 流。我建议您将scanf输入重写为:

while(scanf("%d %d %d %d", &N, &B, &H, &W) != EOF){
    int cost = inf;
    // remove scanf and cin.eof() line here
    ...
}

为了证明我的观点(至少输出):

#include <iostream>
#include <cstdio>

using namespace std;

static __inline__ unsigned long long rdtsc(void)
{
    unsigned hi, lo;
    __asm__ __volatile__ ("rdtsc" : "=a"(lo), "=d"(hi));
    return ( (unsigned long long)lo)|( ((unsigned long long)hi)<<32 );
}

int main(int argc, char **argv)
{

    unsigned long long t = rdtsc();
    if (argc > 1)
    {
        for(int i = 0; i < 1000; i++)
        {
            printf("%d", i);
        }
    }
    else
    {
        for(int i = 0; i < 1000; i++)
        {
            cout << i << "\n";
        }

    }

    t = rdtsc() - t; 
    cerr << "Time: " << t << endl;
}

在不带参数 ( argc == 1) 和带参数 ( argc == 2) 的情况下运行时的输出是:

$ ./a.out > foo.txt
Time: 1672894
$ ./a.out 1 > foo.txt
Time: 1513620

大约有 10% 的差异有利于printf. 但是,当我运行任何基准测试时,我的系统中存在相当多的变化,因此应该小心谨慎。请注意,使用endl而不是"/n"会产生显着差异!

对于cinvs. scanf,对于 的劣势有一点不同scanf

#include <iostream>
#include <cstdio>

using namespace std;

static __inline__ unsigned long long rdtsc(void)
{
    unsigned hi, lo;
    __asm__ __volatile__ ("rdtsc" : "=a"(lo), "=d"(hi));
    return ( (unsigned long long)lo)|( ((unsigned long long)hi)<<32 );
}

int main(int argc, char **argv)
{

    unsigned long long t = rdtsc();
    if (argc > 1)
    {
        for(int i = 0; i < 1000; i++)
        {
            int tmp;
            scanf("%d", &tmp);
        }
    }
    else
    {
        for(int i = 0; i < 1000; i++)
        {
            int tmp;
            cin >> tmp;
        }

    }

    t = rdtsc() - t; 
    cerr << "Time: " << t << endl;
}


$ ./a.out < foo.txt
Time: 1990454
$ ./a.out 1 < foo.txt
Time: 4804226

如您所见,scanf速度慢了近 2.5 倍……但是,我看到其他情况并没有那么大的差异。我不完全确定为什么这里会有如此大的差异。

总之,存在差异,但我相信 James Kanze 的回答更接近于解释发生了什么 - 代码根本无法完成,因为cin.eof()没有设置scanf.

于 2013-08-28T14:06:32.410 回答
1

有一件事是肯定的:scanfstd::cin.eof(). 所以你的第一个代码有一个无限循环。第二个代码实际上从 中读取一些内容std::cin,并最终导致std::cin.eof()返回 true。

然而,这两种代码都有许多其他问题。鉴于你的水平,你应该忘记scanf; 这远非危险和复杂。std::cin到处使用。并在输入之后检查它是否成功,但在使用结果之前(总是)。(std::cin.eof()不会告诉你上一次输入是否成功,也不会告诉你下一次会成功还是失败。直到你知道上一次输入失败,它的使用很可能是一个错误。)

编写代码的惯用方式将涉及以下内容:

while ( std::cin >> N >> B >> H >> W ) ...

(除了没有经验丰富的 C++ 程序员会为它们使用全局变量;就此而言,也不会使用单个大写字母作为名称。)其他输入应以类似方式处理。

于 2013-08-28T14:24:07.587 回答
0

好的。我知道答案就在那里,但我仍然没有看到一个清晰明确的解释,为什么 OP 会观察。因此,为了充分利用 James 和 Mats 的答案,我将尝试得到一个易于理解的解释。

问题是第一个代码本身运行速度并不慢。正如詹姆斯所说,可能存在无限循环。

为什么第一个代码似乎运行得更慢?由于死循环,自动判断超过时限将其杀死。算法和 I/O 并不慢。

鉴于您的时间差异:0.022 秒到 1 秒。由于 c 和 c++ 之间的 I/O 实现差异,不可能(实际上)存在如此大的差异。

我没有输入示例。但我敢打赌,如果您从 Mats 的回答中得到建议,并使用以下代码,第一个代码将正常工作并给出相同的结果。

#include <stdio.h>
#include <stdlib.h>
#define inf 500000000
int N, B, H, W;
int main ()
{
    while(scanf("%d %d %d %d", &N, &B, &H, &W) != EOF){ //Mats' suggestion
        int cost = inf;
        //if(cin.eof()) break; //not needed `while` checks it
        for(int i = 0; i < H; i++){
            int P, k ;
            scanf("%d",&P);
            for(int j = 0; j < W; j++){
                scanf("%d",&k);
                if(k >= N && N*P < cost) cost = N*P;
            }
        }
        if(cost <= B) printf("%d",cost);
        else{
            printf("stay home\n");
        }
    }
    return 0;
}
于 2013-08-28T14:54:28.983 回答