RiseOJ는 solved.ac와 제휴 관계가 없습니다. 티어 아이콘 © solved.ac. solved.ac
← 브론즈 II

2차원 배열

행과 열로 이루어진 표 형태의 데이터 다루기.

기초 & 구현 Bronze II 브론즈 II
선수 지식: 배열
1강 2차원 배열: 격자 데이터 다루기 공식

2차원 배열이란?

2차원 배열 은 값을 행(row)과 열(column) 로 이루어진 격자에 담습니다.
지도, 표, 이미지처럼 "가로 × 세로" 모양의 데이터를 다룰 때 씁니다.
a[i][j]i행 j열의 값입니다.


1. 선언과 입력

격자가 NM열일 때:

C++

#include <bits/stdc++.h>
using namespace std;
int a[1000][1000];
int main() {
    int n, m; cin >> n >> m;
    for (int i = 0; i < n; i++)
        for (int j = 0; j < m; j++)
            cin >> a[i][j];
}

Python

n, m = map(int, input().split())
a = [list(map(int, input().split())) for _ in range(n)]

붙어 있는 숫자 격자(예: 10110)를 한 줄씩 읽을 땐:

a = [list(map(int, input().strip())) for _ in range(n)]

2. 이중 반복으로 순회

for (int i = 0; i < n; i++) {
    for (int j = 0; j < m; j++)
        cout << a[i][j] << ' ';
    cout << '\n';
}

바깥 루프가 , 안쪽 루프가 입니다. 출력할 때 한 행이 끝나면
줄바꿈을 넣는 것을 잊지 마세요.


3. 자주 쓰는 패턴

행 합 / 열 합

for (int i = 0; i < n; i++) {
    long long rowSum = 0;
    for (int j = 0; j < m; j++) rowSum += a[i][j];
}

상하좌우 이웃 보기 — 격자 문제의 핵심 기술입니다.

int dx[4] = {-1, 1, 0, 0};
int dy[4] = {0, 0, -1, 1};
for (int d = 0; d < 4; d++) {
    int ni = i + dx[d], nj = j + dy[d];
    if (ni < 0 || ni >= n || nj < 0 || nj >= m) continue; // 격자 밖이면 건너뜀
    // a[ni][nj] 사용
}

경계 검사(범위 밖이면 무시) 패턴은 미로·영역 문제에서 끊임없이 등장하니
손에 익혀 두세요.


4. 행과 열을 헷갈리지 않기

a[i][j] 에서 앞이 행(세로 위치), 뒤가 열(가로 위치) 입니다. 좌표를
(x, y)로 부르는 문제에서는 어느 쪽이 행인지 한 번 정해 끝까지 지키세요.
보통 a[행][열], 즉 a[y][x]로 두면 헷갈림이 적습니다.


5. 자주 하는 실수

  • 행/열 뒤바꿈a[j][i]처럼 인덱스를 뒤집어 접근. 한 가지 규칙으로 통일하세요.
  • 경계 밖 접근 — 이웃을 볼 때 ni, nj가 격자를 벗어나는데 검사를 빠뜨림. 위 3번의 범위 검사를 항상 넣으세요.
  • 크기 부족 / 초기화 누락N×M보다 작게 잡거나, 누적 배열을 0으로 시작하지 않음.

연습 팁

격자 문제는 작은 예제(예: 3×3)를 종이에 직접 그려 인덱스를 손으로 짚어
보면 훨씬 빨리 이해됩니다. dx/dy 배열로 이웃을 도는 패턴은 한 번 외워 두면
앞으로 나올 수많은 격자·탐색 문제에서 그대로 재사용할 수 있습니다.

2강 2차원 배열을 깊게: 방향과 부분합 공식

2차원 배열을 활용하는 법

행·열 선언과 입력은 익혔다고 보고, 여기서는 격자를 움직이며 정보를 모으는
실전 기법을 다룹니다. 시뮬레이션·DP·탐색의 토대가 됩니다.


1. 행·열 방향 합

int n, m; cin >> n >> m;
int a[100][100];
for (int i = 0; i < n; i++)
    for (int j = 0; j < m; j++) cin >> a[i][j];

for (int i = 0; i < n; i++) {        // 각 행의 합
    int s = 0;
    for (int j = 0; j < m; j++) s += a[i][j];
    cout << s << ' ';
}

열의 합은 ij의 역할을 바꿔 바깥을 j로 돌면 됩니다.


2. 상하좌우 이웃 보기 (방향 배열)

격자 문제의 단골 기법입니다. "위/아래/왼/오른쪽"을 좌표 증감으로 표현합니다.

int dx[4] = {-1, 1, 0, 0};   // 행 변화
int dy[4] = {0, 0, -1, 1};   // 열 변화
for (int d = 0; d < 4; d++) {
    int ni = i + dx[d], nj = j + dy[d];
    if (ni < 0 || ni >= n || nj < 0 || nj >= m) continue;  // 범위 밖 무시
    // a[ni][nj] = (i,j)의 d방향 이웃
}
dx = [-1, 1, 0, 0]
dy = [0, 0, -1, 1]
for d in range(4):
    ni, nj = i + dx[d], j + dy[d]
    if 0 <= ni < n and 0 <= nj < m:
        pass  # 이웃 처리

범위 검사(격자를 벗어났는지)는 절대 빠뜨리면 안 되는 단계입니다. DFS/BFS로
가기 전에 꼭 익혀 두세요.


3. 대각선 순회

정사각 격자의 대각선은 인덱스 관계로 잡습니다.

for (int i = 0; i < n; i++) cout << a[i][i] << ' ';        // 주대각선
for (int i = 0; i < n; i++) cout << a[i][n-1-i] << ' ';    // 반대 대각선

4. 자주 하는 실수

  • 행/열 헷갈림a[i][j]에서 i는 행(세로), j는 열(가로). 일관되게.
  • 범위 검사 누락 — 이웃을 볼 때 격자 밖 접근은 런타임 에러.
  • 크기 부족a[n][m]인데 입력이 더 클 때.

정리

2차원 배열 활용의 핵심 도구는 (1) 행/열 방향 집계, (2) 방향 배열 + 범위 검사
이웃 보기, (3) 대각선 순회입니다. 특히 방향 배열은 격자 탐색의 표준이니 통째로
외워 두세요.

3강 2차원 배열로 푸는 실전 문제 공식

2차원 배열 응용 문제 풀이

격자를 다루는 대표 문제 패턴 — 회전, 누적합, 영역 검사 — 을 코드로 정리합니다.


1. 행렬 90도 회전

새 배열에 옮겨 담는 게 가장 안전합니다.

int a[100][100], b[100][100];
// (i,j) -> 시계 90도 회전 시 (j, n-1-i)
for (int i = 0; i < n; i++)
    for (int j = 0; j < n; j++)
        b[j][n-1-i] = a[i][j];
a = [list(map(int, input().split())) for _ in range(n)]
b = [list(row) for row in zip(*a[::-1])]   # 시계 90도

회전은 "어느 좌표가 어디로 가는가"의 공식만 알면 끝입니다.


2. 2차원 누적합 (구간 합 빠르게)

// psum[i][j] = (0,0)~(i-1,j-1) 직사각형 합
for (int i = 1; i <= n; i++)
    for (int j = 1; j <= m; j++)
        psum[i][j] = a[i-1][j-1] + psum[i-1][j] + psum[i][j-1] - psum[i-1][j-1];

미리 한 번 만들어 두면, 임의 직사각형 합을 \(O(1)\)에 구할 수 있습니다(누적 합
단원에서 깊게 다룹니다). Bronze에선 개념만 알아 두면 충분합니다.


3. 지뢰찾기식 이웃 세기

각 칸 주변 8칸의 지뢰 수를 세는 전형적 문제:

int dx[8] = {-1,-1,-1,0,0,1,1,1};
int dy[8] = {-1,0,1,-1,1,-1,0,1};
for (int i = 0; i < n; i++)
    for (int j = 0; j < m; j++) {
        int cnt = 0;
        for (int d = 0; d < 8; d++) {
            int ni = i+dx[d], nj = j+dy[d];
            if (ni<0||ni>=n||nj<0||nj>=m) continue;
            if (mine[ni][nj]) cnt++;
        }
        // cnt = (i,j) 주변 지뢰 수
    }

8방향 배열은 4방향에 대각선 4개를 더한 것입니다.


4. 함정과 패턴 인식

  • 회전 좌표 공식 — 헷갈리면 3×3으로 손으로 그려 확인.
  • 제자리 수정 위험 — 회전 등에서 같은 배열을 덮으면 꼬임. 새 배열 사용.
  • 8방향 범위 검사 — 모서리 칸에서 밖으로 나가지 않도록.

문제에 "N×N 판", "회전", "주변 칸", "직사각형 영역의 합", "지도/격자" 같은
말이 보이면 2차원 배열 문제입니다.


정리

2차원 배열 문제는 (1) 좌표 변환 공식(회전), (2) 방향 배열로 이웃 처리,
(3) 누적합으로 영역 합 — 이 도구들로 대부분 풀립니다. 헷갈리면 작은 격자로 직접
그려 보세요.