繁体   English   中英

ACM问题。 我的代码有什么问题?

[英]A acm problem. What's wrong in my code?

问题文字:

输入 :输入流包含一组整数Ai(0≤Ai≤1018)。 数字由任意数量的空格和换行符分隔。 输入流的大小不超过256 KB。

输出 :对于从最后一个到第一个的每个数字Ai,应输出其平方根。 每个平方根应打印在单独的行中,小数点后至少应有四位数字。

样品
输入:

1427  0   

876652098643267843 5276538

输出:

2297.0716
936297014.1164
0.0000
37.7757

时限:2.0秒
内存限制:16 MB

C和C ++程序由32位Microsoft Visual C ++ 2010在服务器上编译。在2010年8月3日之前,一直使用Intel C ++ Compiler 7.0。 您可以在此页面上下载Microsoft Visual Studio 2010 Express的免费副本。 使用以下参数调用编译器:

// C
cl /TC /MT /EHsc /O2 /W3 /Za /D "_CRT_SECURE_NO_WARNINGS" 
   /D "_CRT_SECURE_NO_DEPRECATE" /D "ONLINE_JUDGE"

// C++
cl /TP /MT /EHsc /O2 /W3 /Za /D "_CRT_SECURE_NO_WARNINGS" 
   /D "_CRT_SECURE_NO_DEPRECATE" /D "ONLINE_JUDGE"

这是我在gcc 4.3中解决此问题的方法:

#include <iostream>
#include <list>
#include <string>
#include <sstream>
#include <math.h>
#include <algorithm>
#include <iomanip>
#include <stdio.h>

void sqrt_f(double n)
{
    printf ( "%.4f\n", sqrt( static_cast<double>( n ) ) );
}

int main()
{
    std::list<double> numbers;
    std::string sInput;
    getline( std::cin, sInput );
    std::istringstream parse( sInput );
    double tmp;
    while ( parse >> tmp )
        numbers.push_front( tmp );
    std::for_each(numbers.begin(), numbers.end(), sqrt_f);
    return 0;
}

但是判断结果是:答案错误(test1)

有什么问题?

警告:当我写这篇文章时,问题仍然在代码审查站点上,因此它主要是作为代码审查来编写的。 此处仅提及了主要适用于SO(解决输入问题)的部分。

目前,我将假定您已解决了@Jeff Mercado指出的获取问题的问题,例如:

#include <iostream>
#include <list>
#include <string>
#include <sstream>
#include <math.h>
#include <algorithm>
#include <iomanip>
#include <stdio.h>

void sqrt_f(double n)
{
    printf ( "%.4f\n", sqrt( static_cast<double>( n ) ) );
}

int main()
{
    std::list<double> numbers;
    std::string sInput;
    while (getline( std::cin, sInput )) {  // added `while` to process all input
        std::istringstream parse( sInput );
        double tmp;
        while ( parse >> tmp )
            numbers.push_front( tmp );
    }
    std::for_each(numbers.begin(), numbers.end(), sqrt_f);
    return 0;
}

然后,我将忽略您实际提出的问题(关于正确性),并假设满足要求,仅查看(重写)代码。

void sqrt_f(double n)
{
    printf ( "%.4f\n", sqrt( static_cast<double>( n ) ) );
}

我在这里看到了我特别不喜欢的三件事:

  1. 在C ++中使用printf。 iostream通常是首选(尽管我们将看到,在这种情况下,它们更为冗长)。
  2. static_cast似乎完全无关紧要( n已经是一个双精度)。
  3. 关注点分离差。 您正在将计算与I / O相结合。

    std::list<double> numbers;

我没有太多理由在这里使用std::list 您只是在一端插入,然后从头到尾遍历。 使用std::list主要原因是,如果要在列表中间插入/删除某处。 即使这样,也不一定是最佳选择,但是当您只需要在一端插入时,几乎肯定是错误的选择。

std::string sInput;
while (getline( std::cin, sInput )) {  // added `while` to process all input
    double tmp;
    while ( parse >> tmp )
        numbers.push_front( tmp );
}

我没有在这里使用std::getline任何真正原因。 getline主要在您的输入具有面向行的格式时很有用,但是在这里,它只是由一些任意数量的空格分隔的双精度流。 为此,您似乎增加了额外的复杂性,而没有获得很多功能。

我对while (parse >> tmp)的循环也很兴奋。 它肯定比某些替代方法要好,但是我宁愿使用std::copystd::istream_iterator<double> (在这种情况下)将值复制到集合中。

我对您如何在这里使用收藏也不感到特别兴奋。 首先,使用push_front反转顺序。 至少对我来说,如果将数字按原始顺序添加到集合中,然后向后浏览集合,似乎会更容易理解。

    std::for_each(numbers.begin(), numbers.end(), sqrt_f);

...这是导致sqrt_f中责任分工sqrt_f 自从STL进入C ++至今已有15年了,那时我怀疑我看到过多达6种std::for_each好用法。 当您找不到其他更有效的方法时,它可能很有用,但通常应该是您算法的最后选择。

我想如果这样做,我将使用std::vector进行存储(我们只需要在一端添加项目,就可以满足vector提供的功能)。 我将使用std::istream_iterator<double>使用std::copy copy将数据直接从std :: cin std::copy到该向量中。 然后,我将在向量上使用std::transform和一对反向迭代器,并使用ostream_iterator作为输出。 由于固定标志和精度都是“粘性”的,因此在调用std::transform之前,只需将格式设置一次即可获得正确格式的所有输出:

std::cout.setf(std::ios_base::fixed, std::ios_base::floatfield);
std::cout.precision(4);

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM