簡體   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