如何在不到700毫秒的时间内打印巨大的矩阵?

时间:2016-04-12 21:09:36

标签: c++ algorithm

我设法解决了SPOJ问题。它的时间限制为1秒。但我的算法运行时间不到400毫秒,但打印矩阵大约需要2秒。是否可以在不到700毫秒的时间内打印出来?

char matrix[30000][30];

我尝试用两个for循环打印它,然后用printf作为字符串逐行,然后我尝试了put也不是快速的。 我还尝试用put打印一组900000个字符。这是目前最快的方式(1.6s)。

下面的代码是我用数组写的最快的代码(30000 * 30 = 900000)。

#include <iostream>
#include <ctime>
#include<stdio.h>

using namespace std;

int main()
{

    char array[900000];

    for(int i = 0; i < 900000; i++)
        array[i] = '.';


    clock_t time_a = clock();
    puts(array);
    clock_t time_b = clock();
    cout << endl;
    cout << "Execution time of puts: " << (unsigned int)(time_b - time_a) << endl;
    return 0;
}

3 个答案:

答案 0 :(得分:2)

重新发布,评论中已经指出的内容:

  1. 变量array应该为空终止 - 在for循环初始化后需要array[900000-1] = '\0';或者可能发生错误,因为std::put不知道何时停止。< / LI>
  2. 无论是打印到控制台还是文件(这都是SPOJ裁判所做的),确实存在很大差异:
  3. 在我的机器上打印输出到控制台(./program)需要2秒钟,但如果输出通过管道输送到文件(./program > out.txt),则只需0.001秒。

答案 1 :(得分:1)

SPOJ正在寻找控制台上的输出(std::cout)。不幸的是,这使得测试变得非常难看,因为输出需要几秒钟才能打印,使程序运行时偏向图形卡的限制而不是程序本身,并且通用控制台无法保持整个输出,因此很难将输出验证为正确

解决方案一:使用std :: cout将输出打印到控制台,但让操作系统将控制台输出重定向(AKA管道)到文件。这是通过两个窗口上的以下运算符和我玩过的大多数* nix变体来完成的。

program.exe > outputfile.txt

>运算符表示重定向。

简单的黑客测试代码证明如下:

#include <iostream> //cout
#include <chrono> // clock
#include <cstring> //memset

char courtMatrix[90000];

void printFile(char * matrix,
               size_t len)
{
    for (size_t i = 0; i < len - 1; i++)
    {
        std::cout << matrix[i] << "\n";
    }
    std::cout << matrix[len - 1];
}

int main()
{
    // not using c-style standard IO, no sense paying for it.
    std::cout.sync_with_stdio(false);

    //initialize array contents
    memset(courtMatrix, '.', sizeof(courtMatrix));

    //start timer
    auto start = std::chrono::high_resolution_clock::now();
    //TODO generate output here
    //print output
    printFile(courtMatrix, sizeof(courtMatrix));
    // compute duration
    auto dur = std::chrono::duration_cast<std::chrono::nanoseconds>(std::chrono::high_resolution_clock::now() - start);

    //output execution time. Note cerr, not cout. Different data stream and
    //won't pipe to file
    std::cerr << "Execution time : " << dur.count() << std::endl;
    return 0;
}

执行

test > test.txt

典型输出:一个test.txt文件和

  

执行时间:0

关于size_t的快速说明。 size_t是一个无符号整数,足以索引系统上可表示的最大对象。这意味着它足以处理您可以构建的任何阵列。它还消除了测试负数和垃圾的需要,因为负数将包裹到​​一个巨大的正数,并将被上限检查捕获。方便用于索引。

回到主题,上面的printFile函数的输出将被SPOJ拒绝,因为输出要求似乎想要2D矩阵并且偏离这个可能会导致失败。在那种情况下:

void printFile(char * matrix,
               size_t len,
               size_t rowlength)
{
    size_t rowleft = rowlength;
    for (size_t i = 0; i < len; i++)
    {
        std::cout << matrix[i] << ' ';
        rowleft--;
        // test if we've printed an entire row
        if (rowleft == 0)
        {
            // we have, so end the line and reset the counter
            rowleft = rowlength;
            std::cout << '\n';
        }
        /* could use the more elegant-looking

        if (i % rowlength) std::cout << '\n';

        but the % operator is often pretty expensive compared to --
        As always, test it and find out which suits your needs better.
        */
    }
}

不要害怕使用2D数组并在此处嵌套for循环。一旦使用优化编译器,改进的可读性可能会超过任何性能损失。如果我错了,可以通过一些分析会很快告诉你。

答案 2 :(得分:0)

无法将输出重定向到文件,并以某种方式让SPOJ在输出文件中检查您的答案。

但是,可以对您进行一些优化。例如,cout不是向标准输出写入内容的最快方式。

看一下这篇文章:Yet again on C++ input/output

作者讨论并比较了C ++中用于竞争性编程的几种I / O方法。