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

[C언어 백준 풀이][Bronze I] 1252번 : 이진수 덧셈 / 1259번 : 팰린드롬 수 / 1268번 : 임시 반장 정하기

restudy 2021. 8. 26. 14:22
반응형

이번 포스트에서도 역시 C언어를 이용하여 Baekjoon Online Judge의 (solved.ac 기준) Bronze I 난이도의 문제 3개를 해결해보도록 하겠습니다.

풀어볼 문제는 1252번 : 이진수 덧셈, 1259번 : 팰린드롬 수, 1268번 : 임시 반장 정하기입니다.

 

 

1252번 : 이진수 덧셈

 

두 개의 이진수를 더하는 프로그램을 작성하는 간단한 문제입니다.

다만 이진수에서는 1과 1을 더할 때도 자릿수의 올림이 필요하기 때문에, 이를 고려해주어야 합니다.

입력 범위는 2^79까지이므로, long long int 범위는 넘는다고 생각할 수 있습니다. (확인해보니 거의 비슷하게 넘어감)

따라서 문자열을 통한 연산 방식으로 접근해야 합니다.

 

#include<stdio.h>
#include<string.h>

int main() {
    char a[100], b[100], a_rev[100], b_rev[100], ans[100], ans_rev[100];
    int carry, i, length_a, length_b;
    scanf("%s %s", a, b);
    for(i=0; i<strlen(a); i++) a_rev[i] = a[strlen(a)-1-i];
    for(i=0; i<strlen(b); i++) b_rev[i] = b[strlen(b)-1-i];
    a_rev[strlen(a)] = '\0';
    b_rev[strlen(b)] = '\0';
    length_a = strlen(a_rev);
    length_b = strlen(b_rev);
    if(length_a < length_b) for(i=0; i<length_b-length_a; i++) strcat(a_rev, "0");
    if(length_a > length_b) for(i=0; i<length_a-length_b; i++) strcat(b_rev, "0");
    for(i=0; i<strlen(a_rev); i++) {
        if((a_rev[i] - '0') + (b_rev[i] - '0') == 0 && !carry) ans[i] = '0';
        else if((a_rev[i] - '0') + (b_rev[i] - '0') == 1 && !carry) ans[i] = '1';
        else if((a_rev[i] - '0') + (b_rev[i] - '0') == 2 && !carry) ans[i] = '0', carry = 1;
        else if((a_rev[i] - '0') + (b_rev[i] - '0') == 0 && carry) ans[i] = '1', carry = 0;
        else if((a_rev[i] - '0') + (b_rev[i] - '0') == 1 && carry) ans[i] = '0', carry = 1;
        else if((a_rev[i] - '0') + (b_rev[i] - '0') == 2 && carry) ans[i] = '1', carry = 1;
    }
    if(carry) ans[i] = '1', ans[i+1] = '\0';
    else ans[i] = '\0';
    for(i=0; i<strlen(ans); i++) ans_rev[i] = ans[strlen(ans)-1-i];
    ans_rev[strlen(ans)] = '\0';
    for(i=0; i<strlen(ans_rev); i++) if(ans_rev[i] == '1') break;
    if(!strlen(ans_rev+i)) printf("0");
    else printf("%s", ans_rev+i);
}

 

보니까 Python이나 long long int보다 큰 정수를 다룰 수 있는 프로그래밍 언어 기준으로 Bronze I 난이도 문제였네요.

위의 코드도 연산에 문제는 없습니다만, 널 문제 처리 과정에서 채점에 문제가 있는 것 같습니다.

(0으로 시작하는 수나 많은 수의 0 처리, 80자리의 큰 수 대입 모두 다 해보았는데 콘솔에서는 문제가 없습니다.)

우선은 이 문제에 대한 채점은 보류해두고, 나중에 수정할 수 있도록 하겠습니다.

(오류를 아시는 분은 지적해주시면 감사하겠습니다.)

 

 

1259번 : 팰린드롬 수

 

앞에서부터 읽는 순서와 뒤에서부터 읽는 순서가 같은 회문 구조를 가진 숫자를 팰린드롬 수라고 할 때, 입력된 수가 팰린드롬 수인지의 여부를 출력하는 문제입니다.

입력 범위는 99999 이하의 자연수이기 때문에 직접 자릿수 분해를 통해 확인을 해도 되지만, 회문 구조 특성상 문자열로 입력받아 확인하는 것이 더 편합니다.

 

#include<stdio.h>
#include<string.h>

int main() {
    char n[100];
    int check;
    while(1) {
        scanf("%s", n);
        if(!strcmp(n, "0")) return 0;
        check = 1;
        for(int i=0; i<strlen(n)/2; i++) if(n[i] != n[strlen(n)-1-i]) check = 0;
        if(check) printf("yes\n");
        else printf("no\n");
    }
}

 

위와 같이 while문을 하나 만들고 그 안에서 입력을 받아 프로그램 종료 명령어에 해당하는 "0"이 아닌지를 우선 확인합니다.

0이 아닌 경우 check 변수를 이용하여 앞에서부터 비교해나가며 대칭 조건을 만족하지 않는 숫자가 하나라도 있을 경우 check를 0으로 체크하여 팰린드롬수가 아님을 확인할 수 있도록 합니다.

 

 

1268번 : 임시 반장 정하기

 

5학년까지 같은 반이었던 학생들이 가장 많은 학생을 임시 반장으로 선정한다는 규칙 하에, n명의 학생들의 1학년부터 5학년까지의 반이 입력되면 임시 반장을 계산하여 출력하는 문제입니다.

이 때 학생들의 학년 수는 5학년으로 고정이기 때문에, 학생 수만 가변적으로 구현하면 됩니다.

 

 

조건에 임시 반장이 될 수 있는 학생이 여러 명인 경우에는 가장 작은 번호만 출력하라고 되어있는데, 이 조건을 잊어버리고 구현할 경우 예제가 하나밖에 없어서 틀려도 왜 틀렸는지 잠시 헷갈릴 수 있습니다.

 

#include<stdio.h>

int main() {
    int n, classnum[1001][6], check[1001], score[1001] = {0, }, max = 0;
    scanf("%d", &n);
    for(int i=0; i<n; i++)
        for(int j=0; j<5; j++) scanf("%d", &classnum[i][j]);
    for(int i=0; i<n; i++) {
        for(int k=0; k<n; k++) check[k] = 0;
        for(int j=0; j<5; j++)
            for(int k=0; k<n; k++) if(i != k && classnum[i][j] == classnum[k][j]) check[k] = 1;
        for(int k=0; k<n; k++) if(check[k]) score[i]++;
        if(score[i] > max) max = score[i];
    }
    for(int i=0; i<n; i++)
        if(score[i] == max) {
            printf("%d", i+1);
            return 0;
        }
}

 

 

같은 반이 된 학생이 총 몇 번이냐는 중요하지 않고 같은 반이 된 적이 한 번이라도 있는 학생이 몇 명이냐가 중요하기 때문에, 중복 체크를 피해야 합니다.

따라서 저는 check라는 배열을 만들어 먼저 한 학생을 기준으로 다른 학생과 같은 반이 된 적이 있느냐 없느냐를 기준으로 check의 값을 1로 바꾸거나, 0으로 두었습니다.

이후 score 배열을 이용하여 check 되어있는 학생이 몇 명이냐를 계산하였고, 마지막에 이 score의 max 값을 찾아 임시 반장을 정하였습니다.

물론 마지막에 임시 반장(위 코드에서는 score가 max 값인 학생)이 여려 명인 경우에는 앞 번호부터 먼저 나오는 학생의 번호를 출력하였습니다.

 

 

 

 

반응형