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

[C언어 백준 풀이][Bronze III] 진수 변환, 정수를 문자열로 처리하여 푸는 문제 등

restudy 2021. 8. 22. 12:22
반응형

백준 Bronze III 난이도의 문제들부터는 문제가 긴 경우도 있고 코드나 부연설명도 길어지는 경우가 많아 이번 포스트에서는 1009번 : 분산 처리, 1085번 : 직사각형에서 탈출, 1212번 : 8진수 2진수, 1267번 : 핸드폰 요금, 1284번 : 집 주소의 5문제를 풀이하도록 하겠습니다.

 

1009번 : 분산 처리

 

위의 문제를 간단하게 요약하면, input이 7 100인 경우 7^100을 했을 때 일의 자리가 무엇인지 구하는 것입니다.

이것은 컴퓨터가 10대이므로 결국 10으로 나눈 나머지가 마지막 데이터 처리 컴퓨터의 번호가 되기 때문입니다.

따라서 가장 단순한 방법으로는 거듭제곱을 한 뒤 일의 자리를 구하는 방법을 생각할 수 있습니다.

그러나 이 방법은 해결이 불가능할 것으로 보이는 것이, b의 입력 범위가 100만 이하입니다.

따라서 규칙성을 이용하여 해결해야 합니다.

 

#include<stdio.h>

int main() {
    int n, a, b, ans;
    scanf("%d", &n);
    for(int i=0; i<n; i++) {
        scanf("%d %d", &a, &b);
        if(a%10 == 0) ans = 10;
        else if(a%10 == 1) ans = 1;
        else if(a%10 == 2) {if(b%4 == 0) ans = 6; else if(b%4 == 1) ans = 2; else if(b%4 == 2) ans = 4; else if(b%4 == 3) ans = 8;}
        else if(a%10 == 3) {if(b%4 == 0) ans = 1; else if(b%4 == 1) ans = 3; else if(b%4 == 2) ans = 9; else if(b%4 == 3) ans = 7;}
        else if(a%10 == 4) {if(b%2 == 0) ans = 6; else if(b%2 == 1) ans = 4;}
        else if(a%10 == 5) ans = 5;
        else if(a%10 == 6) ans = 6;
        else if(a%10 == 7) {if(b%4 == 0) ans = 1; else if(b%4 == 1) ans = 7; else if(b%4 == 2) ans = 9; else if(b%4 == 3) ans = 3;}
        else if(a%10 == 8) {if(b%4 == 0) ans = 6; else if(b%4 == 1) ans = 8; else if(b%4 == 2) ans = 4; else if(b%4 == 3) ans = 2;}
        else if(a%10 == 9) {if(b%2 == 0) ans = 1; else if(b%2 == 1) ans = 9;}
        printf("%d\n", ans);
    }
}

 

저의 경우에는 나머지로 나올 수 있는 경우의 수가 많아봤자 20개 정도이므로 그냥 분류해서 해결을 빠르게 하는 쪽을 선택했습니다.

100만 제곱 이상을 짧은 시간에 해결하기 위해서는 규칙성을 찾아내는 알고리즘을 찾거나, 일의 자리만 계속 남겨서 곱하거나 하는 방법이 있겠지만 훨씬 더 큰 제곱수를 주더라도 한 번에 찾는 방법을 선택했습니다.

그리고 굳이 배열로 값들을 저장하지 않고 입력을 받는 즉시 출력을 해도 답으로 인정되니 (출력 부분만 읽어서 채점함) 루프를 돌 때마다 출력을 해도 됩니다.

 

이 문제에서 가장 틀리기 쉬운 부분은 10번 컴퓨터가 답으로 나올 때 0이 아닌 10으로 출력해야 한다는 것입니다.

나머지를 출력한다고 생각하기만 하면 헷갈리기 쉬우므로 주의합니다.

 

 

1085번 : 직사각형에서 탈출

 

직사각형 내부에서 직사각형의 변까지 가는 가장 가까운 거리는, 왼쪽 오른쪽 위 아래 네 방향 중 한 가지 방향으로 이동했을 때 구할 수 있습니다. (직사각형의 네 변은 모두 좌표축에 평행하므로 대각선으로 가는 것보다 좌표축에 평행하게 이동하는 것이 최단거리가 됨)

따라서 네 가지 경우를 비교하여 가장 가까운 값을 답으로 출력하면 됩니다.

 

#include<stdio.h>

int main() {
    int x, y, w, h, d;
    scanf("%d %d %d %d", &x, &y, &w, &h);
    d = x;
    if(w-x < d) d = w-x;
    if(y < d) d = y;
    if(h-y < d) d= h-y;
    printf("%d", d);
}

 

 

1212번 : 8진수 2진수

 

8진수가 주어졌을 때 이를 2진수로 변환하는 함수를 만드는 문제입니다.

 

#include<stdio.h>

int main() {
    char c;
    scanf("%c", &c);
    if(c == '1') printf("1");
    else if(c == '2') printf("10");
    else if(c == '3') printf("11");
    else if(c == '4') printf("100");
    else if(c == '5') printf("101");
    else if(c == '6') printf("110");
    else if(c == '7') printf("111");
    else if(c == '0') {
        printf("0");
        return 0;
    }
    while(1) {
        scanf("%c", &c);
        if(c == '\n' || c == '\0') break;
        else if(c == '1') printf("001");
        else if(c == '2') printf("010");
        else if(c == '3') printf("011");
        else if(c == '4') printf("100");
        else if(c == '5') printf("101");
        else if(c == '6') printf("110");
        else if(c == '7') printf("111");
        else if(c == '0') printf("000");
    }
}

8진수 1자리가 2진수로는 3자리로 나타내어진다는 성질을 이용합니다. (8 = 2^3)

숫자를 각 자릿수별로 처리하기 위해 char 형태로 받아주고, 이를 하나씩 변환해줍니다.

oct를 bin으로 코드 한 줄로 변환할 수 있다면 해도 되지만, 저는 8진수가 8가지 숫자밖에 사용하지 않으므로 그냥 각 경우에 대해서 변환을 하는 식으로 처리했습니다.

 

 

1247번 : 부호

연산을 수행하면 범위가 long long int를 무난히 넘어가기 때문에 overflow 값만 추려서 따로 계산하는 식으로 해줘야 합니다.

이 문제가 Bronze III에 랭크된 것은 java나 python 기준이기 때문에 여기서는 우선 넘어가고 다른 문제들을 해결하도록 하겠습니다.

 

 

1267번 : 핸드폰 요금

 

두 요금제 기준으로 계산식을 세워 각각의 요금제에 대한 요금을 구하고, 이를 마지막에 비교하여 적은 요금제의 이름과 가격을 출력하면 되는 문제입니다.

원래는 요금식 계산 함수를 사용하는 편이 바람직하나, 여기서는 간단한 식으로 바로 계산이 되기 때문에 함수를 별도로 이용하지는 않았습니다.

 

#include<stdio.h>

int main() {
    int n, t, sum_y = 0, sum_m = 0;
    scanf("%d", &n);
    for(int i=0; i<n; i++) {
        scanf("%d", &t);
        sum_y += (t/30 + 1) * 10;
        sum_m += (t/60 + 1) * 15;
    }
    if(sum_y < sum_m) printf("Y %d", sum_y);
    else if(sum_y > sum_m) printf("M %d", sum_m);
    else printf("Y M %d", sum_y);
}

 

요금제 정산 단위(예를 들면 영식 요금제는 30초마다 요금 단위가 증가하므로 30)로 나눈 값에 1을 더해주고 거기에 요금제 단위를 곱하면 요금제 요금을 시간에 대한 함수로 구할 수 있습니다.

 

 

1284번 : 집 주소

 

조건에 따라 숫자가 적힐 판의 넓이를 계산하는 문제입니다.

숫자 1을 적을 때는 2cm가, 0을 적을 때는 4cm가 필요하며 그 외의 숫자들은 3cm가 필요하고, 각 숫자 좌우에는 1cm씩 여백이 있어야 합니다.

 

#include<stdio.h>

int main() {
    int a, sum;
    while(1) {
        sum = 1;
        scanf("%d", &a);
        if(a == 0) return 0;
        while(a) {
            if(a%10 == 1) sum += 3;
            else if(a%10 == 0) sum += 5;
            else sum += 4;
            a /= 10;
        }
        printf("%d\n", sum);
    }
}

 

조건은 그다지 복잡하지 않고, 숫자 길이도 정수형을 벗어나지 않으므로 int형 그대로 처리해줘도 됩니다. (범위를 넘어가면 string으로 처리해주어야 함)

저의 경우에는 10으로 나눠가면서 맨 뒷자리 수가 무엇이냐에 따라 판의 길이를 조건에 따라 늘려가는 방식을 선택했습니다.

 

 

 

반응형