KMU/algolab

[KMU - algolab] c++ 프로그래밍 week 2 과제 풀이

happykoa 2020. 4. 6. 14:50

algolab은 국민대학교 소프트웨어학부 수업에서 사용되는 온라인 저지?(과제 제출 사이트)입니다.

 

1주차 과제와 마찬가지로, 2주차 과제 제출 기한이 끝났기 때문에, 한번 풀이를 작성해보겠습니다.

 

5. 직선 그래프 출력하기

C++ 프로그래밍 강의에서는 for문을 다룰 때, 

for(int i = 0; i < n; i++)

 와 같이 0부터 n-1까지 순환하는 반복문을 주로 사용하게 된다고 하셨습니다.

하지만, 제 개인적인 생각으로는 이 문제에서는 0부터 시작하는 반복문을 사용하면 귀찮아집니다.

 

코드를 한번 보겠습니다.

#include <iostream>
using namespace std;
int n,tc,h;
int main() {
    ios::sync_with_stdio(0);
    cin.tie(0);
    cin >> tc;
    while(tc--) {
        cin >> n;
        h = n/2; 
        for(int y= h; y>= -h; y--) {
            for(int x=-h; x<=h; x++) {
                if(x==0 && y ==0) cout << "O";
                else if(x==0) cout << "I";
                else if(y==0) cout << "+";
                else if(x==y) cout<<"*";
                else cout<<".";
            }
            cout<<"\n";
        }
    }
}

코드를 보면, 반복문 내에서 y와 x를 문제 상에서 다루는 좌표계와 동일하게 순회하고, 출력하고 있습니다.

물론 start가 0이 아닙니다. (반복문이 어떻게 순회할 지는 직접 숫자를 몇 개 넣어보면서 직접 종이에 적어보시면 이해가 되실 겁니다.)

 

6. 시간 계산

이 문제는 간단한 수학 문제로 생각될 수 있습니다.

어떤 시각을 다룰 때는, 시/분/초 로 생각하는 게 아닌, 모두 다 초로 변환하여 생각하는 것이 편합니다.

바로 (시 * 3600 + 분 * 60 + 초) 라는 식으로 말이죠.

다시 이 식에서 원래의 시/분/초를 도출하는 방법은 아래 코드에서 확인해주세여(살짝 복잡하게 짜놓은 것 같긴한데, 더 간단하게 할 수 있을 겁니다..아마..?)

 

#include <iostream>
using namespace std;
typedef long long ll;
ll tc,n,H,M,S,h,m,s,total;
ll ans[4];
int main() {
    ios::sync_with_stdio(0);
    cin.tie(0);
    cin >> tc;
    while(tc--) {
        cin >> n;
        total = 0;
        for(int i = 0; i < n; i++) {
            cin >> H >> M >> S >> h >> m >> s;
            total += (h*3600 + m*60 + s)-(H*3600 + M*60 + S);
        }
        ans[0] = total / (3600*24);
        ans[1] = (total % (3600*24)) / 3600;
        ans[2] = ((total % (3600*24)) % 3600) / 60;
        ans[3] = total % 60;
        for(int i=0; i <4; i++) cout << ans[i] <<" ";
        cout << "\n";
    }
}

번외로, 왜 시각을 모두 초로 돌리고 계산해야 하냐? 그냥 시 분 초 따로 계산해서 더하면 되지 않냐라는 질문을 할 수 도 있습니다. 한번 그 생각으로 10시 5분 3초 부터 11시 2분 1초 라는 두 시간의 간격을 구해보시면 이 생각의 문제점을 알 수 있습니다.

 

7. 숫자로 삼각형 출력하기

이 문제는 귀찮게 푸는 풀이도 있고, 간단하게 해결할 수 있는 풀이도 있습니다.

일단 코드부터 보겠습니다.

#include <iostream>
using namespace std;
int tc,n;
int main() {
    ios::sync_with_stdio(0);
    cin.tie(0);
    cin >> tc;
    while(tc--) {
        cin >> n;
        for(int y=1; y<=n; y++) {
            int k = y;
            for(int x=0; x<y; x++) {
                cout << k <<" ";
                k += (n-x-1);
            }
            cout<<"\n";
        }
    }
}

저는 최대한 간단한 풀이를 좋아하기 때문에, 위 코드와 같이 풀었습니다.

이제 이 코드가 어떻게 동작하는지 말해보겠습니다.

문제의 예시를 보자면,

1
2 6
3 7 10
4 8 11 13
5 9 12 14 15

5라는 숫자가 입력되면 이렇게 출력이 되어야 합니다. 그렇죠?

2가지 사실을 살펴보면 됩니다.

1. 첫번째 열의 숫자들은 1 2 3 4 5로 쭉 이어집니다.

2. 같은 행안에 있는 숫자들의 차이는 4(n-1)부터 1씩 감소합니다.

 

이 2가지 사실을 코드에 도입하면 위의 코드와 같이 작성할 수 있습니다

 

8. 모래시계 출력하기

이 문제는...따로 설명할 게 없을 것 같습니다.

그냥 구현해야 하는 문제입니다. :(

#include <iostream>
using namespace std;
int tc,n,h;

int main() {
    ios::sync_with_stdio(0);
    cin.tie(0);
    cin >> tc;
    while(tc--) {
        cin >> n;
        h = n/2;
        for(int y=0; y < h; y++) {
            for(int x=0; x<y; x++) cout << "-";
            cout << "*";
            for(int x=0; x<(h-y); x++) cout << "+*";
            for(int x=0; x<y; x++) cout << "-";
            cout<<"\n";
        }
        for(int y=h; y >= 0; y--) {
            for(int x=0; x<y; x++) cout << "-";
            cout << "*";
            for(int x=0; x<(h-y); x++) cout << "+*";
            for(int x=0; x<y; x++) cout << "-";
            cout<<"\n";
        }
    }
}

 

9. 끝자리  숫자 계산하기

이 문제는 강의에서 여러번 다루었습니다.

#include <iostream>
using namespace std;
int tc,n,a,ret;
int main() {
    ios::sync_with_stdio(0);
    cin.tie(0);
    cin >> tc;
    while(tc--) {
        cin >> n;
        ret = 1;
        while(n--) {
            cin >> a;
            ret *= (a%10);
            ret %=10;
        }
        cout << ret << "\n";
    }
}

이 문제를 풀 때, 왜 틀리는지 모르겠다 할 때는 아래와 같은 케이스에서 틀리는 것일 겁니다.

1
2
2100000013 2111111111

답은 3이겠죠? 오버플로우를 고려하지 않으면 3이 나오지 않을 겁니다. :)

Rmx