코테 및 알고리즘
백준 js - 4963번
Jay_Jung
2024. 8. 8. 16:09
<문제>
https://www.acmicpc.net/problem/4963
<문제 핵심>
1. 테스트케이스가 여러개인 경우 어떻게 처리해야하는지 막혔음
-> while 내부에서 입력을 받음으로써 마지막 0 0 입력값에 도달 했을 때 while문 탈출
-> 각각의 w, h를 받은다음 h 만큼 한줄씩 밑으로 이동하여 그래프를 채운다.
2. bfs를 활용하는 문제이고 대각선으로도 이동할 수 있도록 암묵적 그래프 생성
<문제 풀이과정 및 순서도>
while문 내부에서 흘러가는 로직을 정리하고자 한다.
const input = require("fs")
.readFileSync(process.platform === "linux" ? "/dev/stdin" : "./input.txt")
.toString()
.trim()
.split("\n");
while (input.length > 1) {
const [w, h] = input.shift().split(" ").map(Number);
let temp = h;
const graph = [];
const visited = Array.from({ length: h }, () => Array(w).fill(false));
while (temp > 0) {
graph.push(input.shift().split(" ").map(Number));
temp--;
}
let count = 0;
const bfs = (x, y) => {
const dir = [
[1, 0],
[-1, 0],
[0, 1],
[0, -1],
[1, 1],
[1, -1],
[-1, 1],
[-1, -1],
];
const queue = [[x, y]];
visited[x][y] = true;
while (queue.length) {
const [x, y] = queue.shift();
for (let i = 0; i < 8; i++) {
const [newX, newY] = [x + dir[i][0], y + dir[i][1]];
if (newX >= 0 && newX < h && newY >= 0 && newY < w) {
if (graph[newX][newY] === 1 && visited[newX][newY] === false) {
visited[newX][newY] = true;
queue.push([newX, newY]);
}
}
}
}
};
for (let i = 0; i < h; i++) {
for (let j = 0; j < w; j++) {
if (graph[i][j] === 1 && !visited[i][j]) {
bfs(i, j);
count++;
}
}
}
console.log(count);
}
✅ 마지막 입력값 0 0 에 도달 할 때까지 각각의 테스트 케이스의 w, h를 받는다.
✅ 입력받은 h만큼 한 줄씩 내려가면서 그래프를 생성한다.(이 부분 막혔음)
✅ 0,0부터 시작하는 좌표를 기점으로 그래프의 값이 1(섬)인지 그리고 방문을 안했다면 bfs함수를 호출한다.
-> bfs함수를 호출하게 되면 인접 노드를 탐색하기 때문에 count를 증가시킨다.
✅ 암묵적 그래프는 대각선의 이동도 고려해야 하므로 총 8가지의 방향 배열이 나온다.
✅ 암묵적 그래프의 배열 값과 기존 x, y값을 더한 좌표를 새로운 좌표로 구하고 그래프 상에서 새로운 좌표가 1인지(섬인지) 그리고 방문안했는지를 판단한다. -> 방문 안했다면 방문 처리해주고 큐에 삽입
<전체 코드>
const input = require("fs")
.readFileSync(process.platform === "linux" ? "/dev/stdin" : "./input.txt")
.toString()
.trim()
.split("\n");
while (input.length > 1) {
const [w, h] = input.shift().split(" ").map(Number);
let temp = h;
const graph = [];
const visited = Array.from({ length: h }, () => Array(w).fill(false));
while (temp > 0) {
graph.push(input.shift().split(" ").map(Number));
temp--;
}
let count = 0;
const bfs = (x, y) => {
const dir = [
[1, 0],
[-1, 0],
[0, 1],
[0, -1],
[1, 1],
[1, -1],
[-1, 1],
[-1, -1],
];
const queue = [[x, y]];
visited[x][y] = true;
while (queue.length) {
const [x, y] = queue.shift();
for (let i = 0; i < 8; i++) {
const [newX, newY] = [x + dir[i][0], y + dir[i][1]];
if (newX >= 0 && newX < h && newY >= 0 && newY < w) {
if (graph[newX][newY] === 1 && visited[newX][newY] === false) {
visited[newX][newY] = true;
queue.push([newX, newY]);
}
}
}
}
};
for (let i = 0; i < h; i++) {
for (let j = 0; j < w; j++) {
if (graph[i][j] === 1 && !visited[i][j]) {
bfs(i, j);
count++;
}
}
}
console.log(count);
}
<리팩토링 해본 부분>
✅ for of 문을 통해 배열 요소를 가져오고 dx, dy로 변경 -> x+dx, y+dy로 변경
while (queue.length) {
const [x, y] = queue.shift();
for (let [dx, dy] of dir) {
const [newX, newY] = [x + dx, y + dy];
if (newX >= 0 && newX < h && newY >= 0 && newY < w) {
if (graph[newX][newY] === 1 && visited[newX][newY] === false) {
visited[newX][newY] = true;
queue.push([newX, newY]);
}
}
}
}