리메이크 중/C,C++ 실습 중심

C(&C++) 실습 8. 입출력 속도를 BOJ에 최적화하기

라이피 (Lypi) 2021. 7. 6. 20:00
반응형


문제 출처

backjoon 15552번 문제


0. 문제

ⅰ. N개의 A+B를 입력받고 결과를 출력하라.

■ 입력되는 값은 N은 1이상 1,000,000이하의 값이며 A,B는 1이상 1000이하의 값이다.

■ 프로그램 실행 시간 제한은 1초이다.

■ 온라인 저지나 코딩 테스트를 위해서 실행속도를 높이는 팁이 중심이 되는 문제.


1. 팁

ⅰ. 이제부터 시간과 메모리 제한도 조금씩 신경써야한다.

#include <iostream>
using namespace std;

int main()
{
    int N;
    cin >> N;
    
    int a,b;
    for(int i = 0; i < N; i++) {
        cin >> a >> b;
        cout << a+b << endl;
    }

    return 0;
}

■ 위의 코드는 문제에서 제시하는 출력과 같은 형태로 출력하지만 시간 초과로 틀리게 된다.

◆ 대신에 비슷한 문제인 BOJ 10950번 문제에서는 정답 처리가 된다.

◆ BOJ 10950번 문제에 나타나 있지는 않지만 BOJ 15552번 문제보다 테스트 케이스의 수가 더 적은듯하다.

ⅱ. BOJ에서 화면에 표시되는 형태는 그다지 중요하지 않다.

■ C와 C++에서 제공되는 scanf와 printf는 충분히 빠르므로 별도의 조치가 필요하지 않다.

 

#include <stdio.h>

int main()
{
    int N;
    scanf("%d",&N);
    
    int a,b;
    for(int i = 0; i < N; i++) {
        scanf("%d %d",&a,&b);
        printf("%d\n",a+b);
    }

    return 0;
}

■ 그러므로 c스타일로 이렇게 풀면 시간 초과가 나지 않는다.

 

■ 그러나 C++의 cin과 cout은 그냥 사용하면 시간 초과가 나므로 별도의 조치가 필요하다.

#include <iostream>
using namespace std;

int main()
{
    //추가된 부분 시작
    ios_base::sync_with_stdio(false);   // 1
    cin.tie(NULL);                      // 2-1
    cout.tie(NULL);                     // 2-2
    //추가된 부분 끝

    int N;
    cin >> N;
    
    int a,b;
    for(int i = 0; i < N; i++) {
        cin >> a >> b;
        cout << a+b << "\n";
        // 일부러 endl이 아닌 "\n"을 사용했다.  // 3
    }

    return 0;
}

■ 1. ios_base::sync_with_stdio(false)는 C와 C++의 버퍼를 분리한다. 

■ 1. 그러므로 이를 설정한 뒤에는 cin/cout과 scanf,gets/printf,puts 등 C스타일의 입출력함수를 함께 사용해선 안된다.

■ 1. 또한 이렇게 하면 쓰레드 안정성이 사라지므로 멀티 쓰레드 환경에서는 사용해서는 안된다.

■ 2. cin.tie(NULL)/cout.tie(NULL)은 cin/cout이 다른 입출력스트림과 독립적인 버퍼를 갖게한다. 

■ 2. 이러면 cin과 cout이 각각 독립된 버퍼를 사용하므로 속도가 향상된다.

■ 2. tie를 풀지 않으면 각각을 실행하기 전에 버퍼를 비우는 작업이 포함되기 때문에 속도가 저하된다.

■ 3. endl은 개행문자를 출력하며 버퍼를 비우는 역할도 하는데 버퍼를 비우는 작업은 매우 느리다.

■ 3. 버퍼를 비우면 안정적으로 화면에 출력될 수 있지만 BOJ에서는 화면에 출력되는게 중요하지 않다.

ⅲ. 입력 조건을 코드에 넣을 필요가 없다.

■ 실전에서는 입력 값이 조건에 맞지 않는 경우가 많지만 BOJ에서는 그런 경우가 없다.

■ 즉, 입력값이 조건에 맞는지 체크하는 코드는 필요하지 않다.

■ BOJ의 입력 파일에 들어가있는 테스트케이스가 이미 그 조건들에 맞춰져 있기 때문이다.

ⅳ. 입출력은 공백까지 같게 받아야 한다.

■ 예를 들어 BOJ 15552번 문제는 테스트케이스 갯수 N을 받은 뒤 줄바꿈을 한 뒤 다른 값들을 받는다.

■ 이를 줄바꿈이 아닌 띄어쓰기로 구분해서 받을 경우 틀렸다고 나온다.

■ 출력값도 공백까지 동일하게 출력해야하지만 마지막 출력의 끝부분에는 공백이나 줄바꿈이 들어가도 된다.

ⅴ. 시간 제한과 메모리 제한은 입력 파일 단위이다.

■ BOJ의 테스트케이스는 파일 단위로 입력된다.

■ 즉, 테스트케이스가 4개 들어가있는 파일이 있고, 10000개 들어가있는 파일이 각각 있다는 뜻이다.

■ 시간 제한과 메모리 제한은 각 파일마다 적용되며 하나에서라도 넘을 경우 실패하게 된다.

반응형