React

18290 NM과 K (1)

문제

크기가 N×M인 격자판의 각 칸에 정수가 하나씩 들어있다. 이 격자판에서 칸 K개를 선택할 것이고, 선택한 칸에 들어있는 수를 모두 더한 값의 최댓값을 구하려고 한다. 단, 선택한 두 칸이 인접하면 안된다. r행 c열에 있는 칸을 (r, c)라고 했을 때, (r-1, c), (r+1, c), (r, c-1), (r, c+1)에 있는 칸이 인접한 칸이다.

입력

첫째 줄에 N, M, K가 주어진다. 둘째 줄부터 N개의 줄에 격자판에 들어있는 수가 주어진다.

출력

선택한 칸에 들어있는 수를 모두 더한 값의 최댓값을 출력한다.

제한

1 ≤ N, M ≤ 10
1 ≤ K ≤ min(4, N×M)
격자판에 들어있는 수는 -10,000보다 크거나 같고, 10,000보다 작거나 같은 정수이다.
항상 K개의 칸을 선택할 수 있는 경우만 입력으로 주어진다.

예제 입력 1

1 1 1 1
Plain Text
복사

예제 출력 1

1
Plain Text
복사

예제 입력 2

2 2 2 1 2 3 4
Plain Text
복사

예제 출력 2

5
Plain Text
복사

예제 입력 3

2 2 2 5 4 4 5
Plain Text
복사

예제 출력 3

10
Plain Text
복사

예제 입력 4

5 5 3 1 9 8 -2 0 -1 9 8 -3 0 -5 1 9 -1 0 0 0 0 9 8 9 9 9 0 0
Plain Text
복사

예제 출력 4

27
Plain Text
복사

My solution

N X M 격자
각 칸에는 정수
K 개의 칸 선택해 총합의 최댓값을 구하려 한다.
→ 재귀 호출을 하면서 sum은 매개변수를 통해 누적하고, 배열이 필요하지 않다.
재귀호출의 depth를 호출할 때마다 늘려주는 방식으로 K개의 숫자를 선택했는지 확인한다.
const DFS = (sum, depth) => { if (depth === K) { result = Math.max(sum, result); return; } ... DFS(sum + grid[i][j], depth + 1);
JavaScript
복사
그리고 선택한 두 칸은 인접하면 안된다.
r행 c열의 칸이 (r, c)면 (r-1, c), (r+1, c), (r, c-1), (r, c+1)에 있는 칸이 인접한 칸이다
→ 선택한 칸에서 상하좌우로 한칸씩 이동하면서 이미 방문한 적 있는지 확인하고 방문한 곳이 인접해있는지 검사한다.
const dx = [-1, 1, 0, 0]; const dy = [0, 0, -1, 1]; const isAdjacent = (x, y) => { for (let i = 0; i < 4; i++) { const nx = x + dx[i]; const ny = y + dy[i]; if (nx >= 0 && nx < N && ny >= 0 && ny < M && visited[nx][ny]) { return false; } } return true; };
JavaScript
복사
매번 재귀호출마다 브루트포스로 이차원 배열을 탐색할 때 visited 배열과 함께 인접 여부를 검사해서 해당 칸이 유효한지 걸러낸다.
const DFS = (sum, depth) => { if (depth === K) { result = Math.max(sum, result); return; } for (let i = 0; i < N; i++) { for (let j = 0; j < M; j++) { if (!visited[i][j] && isAdjacent(i, j)) { visited[i][j] = true; DFS(sum + grid[i][j], depth + 1); visited[i][j] = false; } } } };
JavaScript
복사

Code

const solution = function (i) { const [[N, M, K], ...grid] = i .toString() .trim() .split('\n') .map(input => input.split(' ').map(Number)); const visited = Array.from({ length: N }, () => Array.from({ length: M }, () => false) ); const dx = [-1, 1, 0, 0]; const dy = [0, 0, -1, 1]; const isAdjacent = (x, y) => { for (let i = 0; i < 4; i++) { const nx = x + dx[i]; const ny = y + dy[i]; if (nx >= 0 && nx < N && ny >= 0 && ny < M && visited[nx][ny]) { return false; } } return true; }; let result = Number.MIN_SAFE_INTEGER; const DFS = (sum, depth) => { if (depth === K) { result = Math.max(sum, result); return; } for (let i = 0; i < N; i++) { for (let j = 0; j < M; j++) { if (!visited[i][j] && isAdjacent(i, j)) { visited[i][j] = true; DFS(sum + grid[i][j], depth + 1); visited[i][j] = false; } } } }; DFS(0, 0); // BOJ 제출 console.log(result); return result; }; test('TC1', () => { expect( solution(`1 1 1 1`) ).toStrictEqual(1); }); test('TC2', () => { expect( solution(`2 2 2 1 2 3 4`) ).toStrictEqual(5); }); test('TC3', () => { expect( solution(`2 2 2 5 4 4 5`) ).toStrictEqual(10); }); test('TC4', () => { expect( solution(`5 5 3 1 9 8 -2 0 -1 9 8 -3 0 -5 1 9 -1 0 0 0 0 9 8 9 9 9 0 0`) ).toStrictEqual(27); });
JavaScript
복사