본문 바로가기
코딩 테스트/백준

16932 모양 만들기

by 위그든씨 2025. 1. 4.

N×M인 배열에서 모양을 찾으려고 한다. 배열의 각 칸에는 0과 1 중의 하나가 들어있다. 두 칸이 서로 변을 공유할때, 두 칸을 인접하다고 한다.

1이 들어 있는 인접한 칸끼리 연결했을 때, 각각의 연결 요소를 모양이라고 부르자. 모양의 크기는 모양에 포함되어 있는 1의 개수이다.

배열의 칸 하나에 들어있는 수를 변경해서 만들 수 있는 모양의 최대 크기를 구해보자.

입력

첫째 줄에 배열의 크기 N과 M이 주어진다. 둘째 줄부터 N개의 줄에는 배열에 들어있는 수가 주어진다.

출력

첫째 줄에 수 하나를 변경해서 만들 수 있는 모양의 최대 크기를 출력한다.

====

문제 분석

우선 초기 gr에 등록되어 있는 1들끼리 묶어준다. 이때 각각의 영역을 고유의 아이디로 등록한 뒤 해당 아이디에 대해 몇개의 1의 갯수가 등록되어 있는지 객체에 기록해둔다.

for (let i = 0; i < n; i++) {
        for (let j = 0; j < m; j++) {
            if (gr[i][j] !== 1) continue;
            const q = [[i, j]];
            const temp = [[i, j]];
            let cnt = 1;
            num++;
            gr[i][j] = 0;
            while (q.length) {
                const [x, y] = q.shift();
                for (let k = 0; k < 4; k++) {
                    const nx = x + dx[k];
                    const ny = y + dy[k];
                    if (nx < 0 || ny < 0 || nx >= n || ny >= m) continue;
                    if (gr[nx][ny] === 0) continue;
                    gr[nx][ny] = 0;
                    cnt++;
                    q.push([nx, ny]);
                    temp.push([nx, ny]);
                }
            }
            for (const [x, y] of temp) {
                gr[x][y] = num;
            }
            rectangle[num] = cnt;
        }
}

이제 그래프에서 1로 바꿀 수 있는 0을 선택한 뒤 해당 지점으로부터 사방면으로 탐색을 하여 연결할 수 있는 영역을 구한다.

이 때 중복되는 영역을 막기 위해 집합에 담아준다.

이후 사방면의 탐색이 종료되면 각 영역별에 담겨진 1의 갯수를 모두 더해주고 0인 지점을 바꿔줬으며로 1을 추가로 더해준다.

마지막으로 해당 합과 answer를 비교한다

for (let i = 0; i < n; i++) {
        for (let j = 0; j < m; j++) {
            if (gr[i][j] !== 0) continue;
            const s = new Set();
            for (let k = 0; k < 4; k++) {
                const nx = i + dx[k];
                const ny = j + dy[k];
                if (nx < 0 || ny < 0 || nx >= n || ny >= m) continue;
                if (gr[nx][ny] !== 0) {
                    s.add(gr[nx][ny]);
                }
            }

            const sum = [...s].reduce((acc, cur) => acc + rectangle[cur], 1);
            answer = Math.max(answer, sum);
        }
}

정답 코드

const dx = [0, 0, -1, 1];
const dy = [-1, 1, 0, 0];

const main = (n, m, gr) => {
    const rectangle = {};
    let num = 10;

    for (let i = 0; i < n; i++) {
        for (let j = 0; j < m; j++) {
            if (gr[i][j] !== 1) continue;
            const q = [[i, j]];
            const temp = [[i, j]];
            let cnt = 1;
            num++;
            gr[i][j] = 0;
            while (q.length) {
                const [x, y] = q.shift();
                for (let k = 0; k < 4; k++) {
                    const nx = x + dx[k];
                    const ny = y + dy[k];
                    if (nx < 0 || ny < 0 || nx >= n || ny >= m) continue;
                    if (gr[nx][ny] === 0) continue;
                    gr[nx][ny] = 0;
                    cnt++;
                    q.push([nx, ny]);
                    temp.push([nx, ny]);
                }
            }
            for (const [x, y] of temp) {
                gr[x][y] = num;
            }
            rectangle[num] = cnt;
        }
    }
    let answer = Math.max(...Object.entries(rectangle).map((v) => v[1]), 1);

    for (let i = 0; i < n; i++) {
        for (let j = 0; j < m; j++) {
            if (gr[i][j] !== 0) continue;
            const s = new Set();
            for (let k = 0; k < 4; k++) {
                const nx = i + dx[k];
                const ny = j + dy[k];
                if (nx < 0 || ny < 0 || nx >= n || ny >= m) continue;
                if (gr[nx][ny] !== 0) {
                    s.add(gr[nx][ny]);
                }
            }

            const sum = [...s].reduce((acc, cur) => acc + rectangle[cur], 1);
            answer = Math.max(answer, sum);
        }
    }

    console.log(answer);
};

const input = require('fs')
    .readFileSync(process.platform === 'linux' ? '/dev/stdin' : './input.txt')
    .toString()
    .trim()
    .split('\n');

const [n, m] = input[0].split(' ').map((v) => +v);
const gr = [];
for (let i = 1; i < n + 1; i++) {
    gr.push(input[i].split(' ').map((v) => +v));
}
main(n, m, gr);

'코딩 테스트 > 백준' 카테고리의 다른 글

2281 데스노트 (자바스크립트)  (0) 2025.01.07
2293 동전1  (0) 2025.01.06
13398 연속합2  (0) 2025.01.04
5557번 1학년 (자바스크립트)  (0) 2025.01.04
12869 뮤탈리스크  (0) 2025.01.03