자료구조와 알고리즘/문제풀이

[Baekjoon] 단계별로 풀어보기 : 2차원 배열

순정법사 2023.08.25

 

이번 알고리즘 문제 풀이는 C로 진행했습니다 

코드에 오탈자나 문제가 있으면 언제든지 댓글로 알려주세요!

 

 

 


 

 

 

A. 2차원 배열

 

2차원 배열 단계

2차원 배열을 활용하여 색종이로 평면을 덮는 문제

www.acmicpc.net

 

1. 행렬 덧셈

a. 문제지  : 10807

 

b. 알고리즘 / 풀이

1) 2차원 배열을 1차원 배열로 풀어서 계산

 

  1. n과 m을 입력받아 행렬의 크기를 설정
  2. totalnum을 n * m으로 계산하여 배열의 총 원소 수를 계산
  3. 첫 번째 배열 numarr1과 두 번째 배열 numarr2를 선언
  4. 첫 번째 배열 numarr1에 n 행과 m 열에 대한 원소들을 순서대로 입력
  5. count 변수를 초기화
  6. 두 번째 배열 numarr2에 n 행과 m 열에 대한 원소들을 순서대로 입력
  7. 두 배열의 같은 인덱스의 값을 더함
  8. count 변수를 다시 초기화
  9. 첫 번째 배열 numarr1을 출력하되, 각 행마다 m 개의 원소를 공백으로 구분하여 출력한 후 줄바꿈

 

👉 행렬을 1차원으로 선언하는건 연산이나 처리를 수행하기 어려워 적합하지 않지만 아주 조금 더 빠르다..!

 

2) 2차원 배열 그대로 연산

 

  1. n과 m을 입력받아 행렬의 크기를 설정
  2. A와 B 행렬, 그리고 결과 행렬 result을 선언
  3. 첫 번째 행렬 A와 두 번째 행렬 B를 입력받아 각 행렬에 값을 저장
  4. A와 B를 더하여 결과 행렬 result을 생성
  5. result 행렬을 출력

 

c. 정답

📚 풀이 : 2차원 배열을 1차원으로 풀어 계산

#include <stdio.h>

int main() {
    int n, m, totalnum, count = 0;
    scanf("%d %d", &n, &m);
    
    totalnum = n * m;
    int numarr1[totalnum];  // 첫 번째 배열
    int numarr2[totalnum];  // 두 번째 배열
    
    // 첫 번째 배열 입력
    for (int i = 0; i < n; i++) {
        for (int j = 0; j < m; j++) {
            scanf("%d", &numarr1[count++]);
        }
    }
    
    count = 0;  // count 초기화
    
    // 두 번째 배열 입력 및 두 배열의 값을 더함
    for (int i = 0; i < n; i++) {
        for (int j = 0; j < m; j++) {
            scanf("%d", &numarr2[count]);
            numarr1[count] += numarr2[count];  // 두 배열의 값을 더함
            count++;
        }
    }
    
    count = 0;  // count 초기화
    
    // 더해진 결과 출력
    for (int i = 0; i < n; i++) {
        for (int j = 0; j < m; j++) {
            printf("%d ", numarr1[count++]);
        }
        printf("\n");
    }
    
    return 0;
}

 

📚 풀이 : 2차원 배열로 덧셈

#include <stdio.h>

int main() {
    int n, m;
    scanf("%d %d", &n, &m);

    int A[n][m]; // 행렬 A
    int B[n][m]; // 행렬 B
    int result[n][m]; // 더한 결과 행렬

    // 행렬 A 입력
    for (int i = 0; i < n; i++) {
        for (int j = 0; j < m; j++) {
            scanf("%d", &A[i][j]);
        }
    }

    // 행렬 B 입력
    for (int i = 0; i < n; i++) {
        for (int j = 0; j < m; j++) {
            scanf("%d", &B[i][j]);
        }
    }

    // 행렬 A와 B를 더하여 결과 행렬 생성
    for (int i = 0; i < n; i++) {
        for (int j = 0; j < m; j++) {
            result[i][j] = A[i][j] + B[i][j];
        }
    }

    // 결과 행렬 출력
    for (int i = 0; i < n; i++) {
        for (int j = 0; j < m; j++) {
            printf("%d ", result[i][j]);
        }
        printf("\n");
    }

    return 0;
}

 

 

2. 최댓값

a. 문제지  : 2566

 

b. 정답

📚 풀이

#include <stdio.h>

int main() {
    int arr[9][9];
    int bigNum = 0, newi = 0, newj = 0;
    
    // 9x9 격자판의 숫자를 입력 받아 배열 arr에 저장
    for (int i = 0; i < 9; i++) {
        for (int j = 0; j < 9; j++) {
            scanf("%d", &arr[i][j]);
            
            // 입력된 숫자가 현재까지의 최댓값보다 크다면 최댓값과 위치 업데이트
            if (bigNum < arr[i][j]) {
                bigNum = arr[i][j];
                // 여기서 1을 더하지 않는 이유는, 만약 모든 숫자가 0일 경우
                // 이 조건문을 통과하지 않기 때문에
                // 아래 최소 출력값이 1이여야 하는 newi, newj가 0 0 으로 나옴
                newi = i; // 최댓값 위치의 행
                newj = j; // 최댓값 위치의 열
            }
        }
    }
    
    // 최댓값과 해당 위치 출력
    printf("%d\n", bigNum);         // 최댓값 출력
    printf("%d %d\n", newi + 1, newj + 1); // 최댓값 위치 출력 (1부터 시작)
    
    return 0;
}

 

 

3. 세로 읽기

a. 문제지  : 10798

 

b. 알고리즘 / 풀이

  1. 다섯 줄의 단어를 입력받아 각각의 단어를 배열에 저장
  2. 각 단어의 길이를 계산하여 word_lengths 배열에 저장
  3. max_length 변수에는 다섯 개 단어의 길이 중 최대 값을 저장
  4. 결과 문자열 result를 초기화
  5. 열(column)별로 순회하면서 각 행(row)의 글자를 결과 문자열에 추가
    a) 열 순회: col 변수를 0부터 max_length까지 증가
    b) 행 순회: row 변수를 0부터 4까지 증가
    c) 만약 현재 열 col이 해당 행 row의 단어 길이(word_lengths[row])보다 작을 때, 해당 위치에 글자가 있으므로 결과 문자열에 해당 글자를 추가

 

마지막 출력하는걸 쉽게 말하자면 2차원 배열을 뒤집어 열과 행을 반대로 출력하는데,

원래는 행의 요소들을 하나씩 먼저 추출했다면, 이번엔 열의 요소들을 먼저 추출함

그때 열의 요소가 있는지 없는지 확인하기 위해 단어 5개의 길이를 저장해두고

조건문로 그 열에 도달했을 때 (문자를 추출하기 위해)  길이를 비교 함

 

c. 정답

📚 풀이

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

int main() {
    char words[5][16]; // 최대 15글자의 단어를 5개까지 받을 수 있는 배열
    int word_lengths[5] = {0}; // 단어들의 길이를 저장하는 배열
    int max_length = 0; // 단어들 중 최대 길이

    // 다섯 줄의 단어를 입력받음
    for (int i = 0; i < 5; i++) {
        scanf("%s", words[i]); // 한 줄에 있는 단어를 받음
        word_lengths[i] = strlen(words[i]); // 단어의 길이 저장
        if (word_lengths[i] > max_length) {
            max_length = word_lengths[i]; // 최대 길이 갱신
        }
    }

    // 결과 문자열을 저장할 배열
    char result[76] = ""; // 최대 글자 수 5 * 15 + 1 (NULL 문자)

    // 각 열(column)별로 순회
    for (int col = 0; col < max_length; col++) {
        for (int row = 0; row < 5; row++) {
            // 해당 위치의 글자가 있으면 결과 문자열에 추가
            if (col < word_lengths[row]) {
                strncat(result, &words[row][col], 1); // 한 글자씩 결과에 추가
            }
        }
    }

    // 결과 출력
    printf("%s\n", result);

    return 0;
}

 

 

4. 색종이

a. 문제지  : 2563

 

b. 풀이 / 알고리즘

0) 문제 이해

 

가로, 세로 크기가 각각 100인 정사각형 모양의 흰색 도화지 각 100개의 값이 들어가는 2차원 배열 0 초기화

가로, 세로 크기가 각 10인 정사각형 모양의 검은색 색종이 1로 변경될 값들

검은 영역의 넓이 2차원 배열을 순회하며 값이 1인 데이터를 카운팅

 

1) 입력

 

색종이의 수 ➡ 반복문

색종이를 붙인 x,y 위치 ➡ 2차원 배열 값을 변경할 시작점 ~ 10 추가

 

2) 출력

 

2차원 배열을 순회하면서 1의 값을 카운팅 후 출력

 

3) 최종 알고리즘

  1. 가로, 세로 크기가 100인 정사각형 모양의 흰색 도화지를 생성하고, 초기값을 0으로 설정
  2. 색종이의 수 입력
  3. 각 색종이마다 위치를 입력받아 해당 위치에서 10x10 크기의 영역을 1로 설정
  4. 흰색 도화지를 순회하며 1로 설정된 영역의 개수를 세어 검은 영역의 넓이를 구함

 

c. 정답

📚 풀이

#include <stdio.h>

int main() {
    int white[101][101] = {0}; // 흰색 도화지 배열 초기화
    int n = 0; // 직사각형 개수
    scanf("%d", &n); // 직사각형 개수 입력받음
    
    // 직사각형 개수만큼 반복
    for (int i = 0; i < n; i++) {
        int blkX = 0, blkY = 0; // 직사각형 좌표 초기화
        scanf("%d %d", &blkX, &blkY); // 직사각형의 왼쪽 상단 좌표 입력받음
        
        // 10x10 크기의 직사각형 부분을 색칠
        for (int j = blkY; j < blkY + 10; j++) {
            for (int k = blkX; k < blkX + 10; k++) {
                white[j][k] = 1; // 해당 위치를 색칠한 상태로 표시
            }
        }
    }
    
    int count = 0; // 색칠된 부분의 개수 초기화
    
    // 흰색 도화지를 순회하며 색칠된 부분의 개수를 센다
    for (int i = 0; i < 100; i++) {
        for (int j = 0; j < 100; j++) {
            if (white[i][j] == 1) {
                count++; // 색칠된 부분을 찾으면 개수를 증가시킴
            }
        }
    }
    
    printf("%d", count); // 색칠된 부분의 개수 출력
    return 0;
}