알고리즘/백준(BOJ) 문제풀이

[C++ 백준 풀이][Bronze III] 기초 연산 20문제 간단 풀이 (3)

restudy 2021. 12. 16. 03:10
반응형

이 포스트에서는 프로그래밍 문제 사이트 백준 Online Judge의 Bronze III 난이도에 해당하는 문제들의 풀이 코드와 간략한 해설을 다룰 것입니다.

 

풀 문제의 수는 총 20문제이고, 포스트 길이가 길어질 수 있기 때문에 간단하게만 설명을 언급하고 넘어가도록 하겠습니다.

 

 

5217번 : 쌍의 합

#include <cstdio>
using namespace std;

int main() {
    int T, n;
    scanf("%d", &T);
    for(int i=0; i<T; i++) {
        scanf("%d", &n);
        printf("Pairs for %d:", n);
        for(int j=1; j<(n+1)/2; j++) {
            printf(" %d %d", j, n-j);
            if(n-j-j > 2) printf(",");
        }
        printf("\n");
    }
}

 

두 수의 합이 n이 되는 쌍들을 오름차순으로 출력하되, 중복되는 두 수는 나오지 않도록 출력하는 문제입니다.

마지막 쌍에는 쉼표를 붙이면 안되기 때문에, 이를 검사하는 조건문 역시 추가해주어야 합니다. (1/20)

 

 

16917번 : 양념 반 후라이드 반

#include <cstdio>
using namespace std;

int main() {
    int a, b, c, x, y;
    scanf("%d %d %d %d %d", &a, &b, &c, &x, &y);
    if(x >= y && a >= c*2) printf("%d", 2*c*x);
    else if(x <= y && b >= c*2) printf("%d", 2*c*y);
    else if(a+b <= c*2) printf("%d", a*x + b*y);
    else {
        if(x <= y) printf("%d", 2*c*x + b*(y-x));
        else printf("%d", 2*c*y + a*(x-y));
    }
}

 

간단히 계산하면 될 것 같은 문제지만, 예제 입력 3번을 보면 함정이 있습니다.

만약 양념 반 후라이드 반 메뉴가 어느 한 메뉴의 절반 가격도 안 된다면, 예를 들어 양념 한 마리를 버리더라도 양념 반 후라이드 반 두 개를 시켜서 후라이드 한 마리를 마련하는 방법이 더 나을 수도 있습니다.

상식적으로만 접근하면 발생하는 예외에 대해 잘 일깨워준 문제인 것 같습니다. (2/20)

 

 

7510번 : 고급 수학

#include <cstdio>
using namespace std;

int main() {
    int T, a, b, c;
    scanf("%d", &T);
    for(int i=1; i<=T; i++) {
        printf("Scenario #%d:\n", i);
        scanf("%d %d %d", &a, &b, &c);
        if(a*a+b*b == c*c || b*b+c*c == a*a || c*c+a*a == b*b) printf("yes\n\n");
        else printf("no\n\n");
    }
}

 

삼각형의 세 변을 입력받아 직각삼각형인지를 검사하는 문제입니다.

세 수를 굳이 정렬하지 않더라도 어느 한 쌍이 다른 빗변과 직각삼각형을 이루는지 확인하면 되므로, 위의 코드의 조건식을 이용해주면 됩니다. (3/20)

 

 

10419번 : 지각

#include <cstdio>
using namespace std;

int main() {
    int T, j, n;
    scanf("%d", &T);
    for(int i=0; i<T; i++) {
        scanf("%d", &n);
        for(j=0; j<=1000; j++) {
            if(j+j*j > n) break;
        }
        printf("%d\n", j-1);
    }
}

 

s + t = t^t + t가 수업 시간을 넘어버리게 되면 안되므로, 넘어버리는 최초의 t-1을 답으로 출력해주면 됩니다. (4/20)

 

 

16561번 : 3의 배수

#include <cstdio>
using namespace std;

int main() {
    int n;
    scanf("%d", &n);
    n /= 3;
    printf("%d", (n-1)*(n-2)/2);
}

 

n을 3으로 나누면, 그냥 자연수를 3개로 분할하는 방법의 수를 출력하는 문제입니다.

이는 n개 가운데 2개의 구분선을 놓아 수를 분리하는 경우의 수이므로, n-1 C 2에 해당합니다.

따라서 (n-1)*(n-2)/2를 답으로 출력해주면 됩니다. (5/20)

 

 

2991번 : 사나운 개

#include <cstdio>
using namespace std;

int main() {
    int a, b, c, d, p, m, n, sum1 = 0, sum2 = 0, sum3 = 0;
    scanf("%d %d %d %d %d %d %d", &a, &b, &c, &d, &p, &m, &n);
    if(p%(a+b) > 0 && p%(a+b) <= a) sum1++;
    if(p%(c+d) > 0 && p%(c+d) <= c) sum1++;
    if(m%(a+b) > 0 && m%(a+b) <= a) sum2++;
    if(m%(c+d) > 0 && m%(c+d) <= c) sum2++;
    if(n%(a+b) > 0 && n%(a+b) <= a) sum3++;
    if(n%(c+d) > 0 && n%(c+d) <= c) sum3++;
    printf("%d\n%d\n%d", sum1, sum2, sum3);
}

 

첫 번째 개를 예시로 들면, 시간을 a+b로 나눈 나머지를 이용하여 상태를 확인할 수 있습니다.

만약 나머지가 0보다 크고 a 이하이면 공격적인 상태이고, 그렇지 않으면 공격적이지 않은 상태입니다. (6/20)

 

 

6131번 : 완전 제곱수

#include <cstdio>
using namespace std;

int main() {
    int N, a, b, cnt = 0;
    scanf("%d", &N);
    for(int i=1; i<=500; i++)
        for(int j=i; j<=500; j++)
            if(j*j - i*i == N) cnt++;
    printf("%d", cnt);
}

 

A와 B의 범위가 1 이상 500 이하이고, B가 A 이상이므로 이를 이용하여 브루트포스 알고리즘으로 모든 범위를 탐색할 수 있습니다. (7/20)

 

 

15633번 : Fan Death

#include <cstdio>
using namespace std;

int main() {
    int n, sum = 0;
    scanf("%d", &n);
    for(int i=1; i<=n; i++) {
        for(int j=1; j<=n; j++) {
            if(i*j == n) sum += i;
        }
    }
    printf("%d", sum*5-24);
}

 

주어진 수의 약수의 합을 구하고 5를 곱하고 24를 빼서 출력해주면 됩니다. (8/20)

 

 

17618번 : 신기한 수

#include <cstdio>
using namespace std;

int main() {
    int N, temp, sum, cnt = 0;
    scanf("%d", &N);
    for(int i=1; i<=N; i++) {
        temp = i;
        sum = 0;
        while(temp) {
            sum += temp%10;
            temp /= 10;
        }
        if(i%sum == 0) cnt++;
    }
    printf("%d", cnt);
}

 

서브태스크가 있지만 브론즈 문제이기에 일일이 반복문으로 구현해도 시간초과에 걸리지 않습니다.

temp, sum, cnt 등 변수를 많이 세워야 하니 헷갈리지 않도록 주의합니다. (9/20)

 

 

14491번 : 9진수

#include <cstdio>
using namespace std;

int main() {
    int N, arr[100], cnt = 0;
    scanf("%d", &N);
    while(N) {
        arr[cnt++] = N%9;
        N /= 9;
    }
    for(int i=cnt-1; i>=0; i--) printf("%d", arr[i]);
}

 

진수 변환 알고리즘은 항상 알고 있어야 합니다.

n진수로 변환할 때, n으로 나눈 나머지를 배열에 저장한 뒤 역순으로 출력해주면 됩니다. (10/20)

 

 

14909번 : 양수 개수 세기

#include <cstdio>
using namespace std;

int main() {
    int n, cnt = 0;
    while(scanf("%d", &n) != EOF) {
        if(n > 0) cnt++;
    }
    printf("%d", cnt);
}

 

입력의 종료가 주어지지 않는데, 그럴 때는 scanf가 EOF를 반환하는지 확인하여 종료해주면 됩니다. (11/20)

 

 

11134번 : 쿠키 애호가

#include <cstdio>
using namespace std;

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

 

나머지가 1이라도 존재한다면 쿠키를 하루 더 먹을 수 있으므로, 경우에 따라 조건문을 세워서 나누어주어야 합니다. (12/20)

 

 

13698번 : Hawk eyes

#include <cstdio>
#include <cstring>
using namespace std;

int main() {
    int s = 1, b = 4;
    char mix[205];
    scanf("%s", mix);
    for(int i=0; i<strlen(mix); i++) {
        if(mix[i] == 'A') {
            if(s == 1) s = 2;
            else if(s == 2) s = 1;
            if(b == 1) b = 2;
            else if(b == 2) b = 1;
        }
        if(mix[i] == 'B') {
            if(s == 1) s = 3;
            else if(s == 3) s = 1;
            if(b == 1) b = 3;
            else if(b == 3) b = 1;
        }
        if(mix[i] == 'C') {
            if(s == 1) s = 4;
            else if(s == 4) s = 1;
            if(b == 1) b = 4;
            else if(b == 4) b = 1;
        }
        if(mix[i] == 'D') {
            if(s == 2) s = 3;
            else if(s == 3) s = 2;
            if(b == 2) b = 3;
            else if(b == 3) b = 2;
        }
        if(mix[i] == 'E') {
            if(s == 2) s = 4;
            else if(s == 4) s = 2;
            if(b == 2) b = 4;
            else if(b == 4) b = 2;
        }
        if(mix[i] == 'F') {
            if(s == 3) s = 4;
            else if(s == 4) s = 3;
            if(b == 3) b = 4;
            else if(b == 4) b = 3;
        }
    }
    printf("%d\n%d", s, b);
}

 

쉬운 야바위 구현문제이지만, 섞는 방법의 수가 6가지이고, 단순히 공이 2개인 것이 아니라 크기가 다른 공 2개이므로 이를 구분해서 다루어야 합니다. (13/20)

 

 

9501번 : 꿍의 우주여행

#include <cstdio>
using namespace std;

int main() {
    int T, N, cnt;
    double D, a, b, c;
    scanf("%d", &T);
    for(int i=0; i<T; i++) {
        cnt = 0;
        scanf("%d %lf", &N, &D);
        for(int j=0; j<N; j++) {
            scanf("%lf %lf %lf", &a, &b, &c);
            if(D/a * c <= b) cnt++;
        }
        printf("%d\n", cnt);
    }
}

 

거리 / 최고 속도 = 이동 시간이므로, 여기에 연료 소비율을 곱한 값이 총 연료 양보다 적거나 같으면 도달할 수 있습니다. (14/20)

 

 

12756번 : 고급 여관

#include <cstdio>
using namespace std;

int main() {
    int a, b, c, d;
    scanf("%d %d %d %d", &a, &b, &c, &d);
    while(b > 0 && d > 0) {
        b -= c;
        d -= a;
    }
    if(b <= 0 && d <= 0) printf("DRAW");
    else if(b > 0 && d <= 0) printf("PLAYER A");
    else if(b <= 0 && d > 0) printf("PLAYER B");
}

 

수의 범위가 작으므로 나눗셈을 하지 않고 그냥 반복해서 빼는 방법으로도 해결이 가능합니다. (15/20)

 

 

2721번 : 삼각수의 합

#include <cstdio>
using namespace std;

int main() {
    int T, N, sum;
    scanf("%d", &T);
    for(int i=0; i<T; i++) {
        scanf("%d", &N);
        sum = 0;
        for(int j=1; j<=N; j++) sum += j*(j+1)*(j+2)/2;
        printf("%d\n", sum);
    }
}

 

T(n) = n*(n+1)/2이므로 W(n) = n*T(n+1) = n*(n+1)*(n+2)/2 임을 이용하여 계산해주면 됩니다. (16/20)

 

 

15820번 : 맞았는데 왜 틀리죠?

#include <cstdio>
using namespace std;

int main() {
    int N, M, a, b, check1 = 1, check2 = 1;
    scanf("%d %d", &N, &M);
    for(int i=0; i<N; i++) {
        scanf("%d %d", &a, &b);
        if(a != b) check1 = 0;
    }
    for(int i=0; i<M; i++) {
        scanf("%d %d", &a, &b);
        if(a != b) check2 = 0;
    }
    if(check1 && check2) printf("Accepted");
    else if(!check1) printf("Wrong Answer");
    else if(check1 && !check2) printf("Why Wrong!!!");
}

 

체크 포인트 2개를 만들어서 예제 전용과 실제 채점 전용을 따로 체크해주면 쉽습니다.

만점이 50점인 문제이므로, 50점이 나와도 당황하지 마시기 바랍니다. (17/20)

 

 

5692번 : 팩토리얼 진법

#include <cstdio>
using namespace std;

int main() {
    int n, temp, fac, sum, mul;
    while(1) {
        scanf("%d", &n);
        if(!n) break;
        temp = n;
        mul = 1;
        fac = 1;
        sum = 0;
        while(temp) {
            sum += (temp%10) * mul;
            temp /= 10;
            mul *= ++fac;
        }
        printf("%d\n", sum);
    }
}

 

팩토리얼 계산 때문에 변수를 많이 선언해야 해서 헷갈릴수도 있겠지만, 곱해지는 수에 1을 더해서 계속 곱해주고 이것을 1의 자리에 계속 곱해주면 쉽게 구할 수 있습니다. (18/20)

 

 

13416번 : 주식 투자

#include <cstdio>
using namespace std;

int main() {
    int T, N, a, b, c, sum = 0, Max;
    scanf("%d", &T);
    for(int i=0; i<T; i++) {
        scanf("%d", &N);
        sum = 0;
        for(int j=0; j<N; j++) {
            scanf("%d %d %d", &a, &b, &c);
            if(a < 0 && b < 0 && c < 0) continue;
            Max = 0;
            if(a > Max) Max = a;
            if(b > Max) Max = b;
            if(c > Max) Max = c;
            sum += Max;
        }
        printf("%d\n", sum);
    }
}

 

모든 회사에서 손실이 발생하는 경우에는 투자를 하지 않아야 한다는 조건만 추가하면 쉽게 해결이 가능한 문제입니다. (19/20)

 

 

18247번 : 겨울왕국 티켓 예매

#include <cstdio>
using namespace std;

int main() {
    int T, N, M;
    scanf("%d", &T);
    for(int i=0; i<T; i++) {
        scanf("%d %d", &N, &M);
        if(N < 12 || M < 4) printf("-1\n");
        else printf("%d\n", M*11 + 4);
    }
}

 

L은 12번째 알파벳이므로, L열 4번째 좌석의 번호는 11*M + 4가 됩니다. (20/20)

 

 

결과

 

현재까지 총 546문제를 해결하여 1758위에 랭크되었습니다.

 

 

 

반응형