jiho_bae
Go devlog
jiho_bae
전체 방문자
오늘
어제
  • 분류 전체보기 (158)
    • JavaScript (38)
      • theory (34)
      • vanilla (4)
    • HTML & CSS (2)
    • Browser (3)
    • CS (6)
      • linux (1)
      • shell (2)
      • compiler (2)
    • DS & Algorithm (87)
      • theory (5)
      • basic (7)
      • programmers (30)
      • baekjoon (45)
    • Design Pattern (2)
    • Error (4)
    • Git & Github (4)
    • Tools (1)
    • 부트캠프 (4)
    • Small Tips (2)
    • Java (3)
    • test (1)

블로그 메뉴

  • 홈
  • 태그
  • 방명록

공지사항

인기 글

태그

  • 계수정렬 자바스크립트
  • 카카오 코딩테스트 양궁대회 nodeJS
  • 병합정렬 자바스크립트
  • javascript use strict
  • 깃 이전 커밋에서 새 브랜치 만들기
  • 백준 17406 nodeJS
  • 1753 최단경로 javascript
  • 자바스크립트 배열의 특수함
  • 백준 자바스크립트 입력 템플릿
  • safari Date format NaN
  • safari invalid date error
  • 리액트 프로젝트 디버깅하기
  • 덧칠하기 javascript
  • 25632 소수 부르기 게임
  • 자바스크립트 채팅방 스크롤
  • 대충만든자판 javascript
  • fetch 취소하기
  • 자바스크립트 이벤트 위임
  • 자바스크립트 비동기 마이크로 태스크 큐와 렌더링 과정
  • 자바스크립트 sort는 왜 그모양일까
  • 외벽 점검 javascript
  • 자바스크립트 모듈 시스템
  • 억억단을 외우자 javascript
  • 리코쳇 로봇 javascript
  • 퀵정렬 자바스크립트
  • 13460 javascript nodejs
  • JavaScript
  • 프로그래머스 숫자카드나누기 javascript
  • 가사 검색 자바스크립트
  • 자바스크립트 커링

최근 댓글

최근 글

티스토리

hELLO · Designed By 정상우.
jiho_bae
DS & Algorithm/baekjoon

[백준] 17406번 배열 돌리기 4 - 자바스크립트

[백준] 17406번 배열 돌리기 4 - 자바스크립트
DS & Algorithm/baekjoon

[백준] 17406번 배열 돌리기 4 - 자바스크립트

2022. 4. 15. 18:42

문제

 

17406번: 배열 돌리기 4

크기가 N×M 크기인 배열 A가 있을때, 배열 A의 값은 각 행에 있는 모든 수의 합 중 최솟값을 의미한다. 배열 A가 아래와 같은 경우 1행의 합은 6, 2행의 합은 4, 3행의 합은 15이다. 따라서, 배열 A의

www.acmicpc.net


 

코드

function sol(input) {
  const [N, M, K] = input[0].split(' ').map(Number);
  let boards;
  let answer = Number.MAX_SAFE_INTEGER;
  const rotateOperations = input
    .slice(1 + N)
    .map((str) => str.split(' ').map(Number));

  dfs(0, []);

  return answer;

  function dfs(L, orders) {
    if (orders.length === K) {
      boards = input.slice(1, 1 + N).map((row) => row.split(' ').map(Number));

      orders.forEach((order) =>
        rotate2DMatrixBy1Step(...rotateOperations[order])
      );

      boards.forEach((row) => {
        const min = row.reduce((acc, val) => acc + val, 0);
        answer = Math.min(answer, min);
      });
      return;
    }

    for (let i = 0; i < K; i++) {
      if (orders.includes(i)) continue;
      dfs(L + 1, [...orders, i]);
    }
  }

  function rotate2DMatrixBy1Step(r, c, s) {
    const n = 2 * s + 1;
    const startR = r - s - 1;
    const startC = c - s - 1;

    const result = Array.from({ length: n }, () => new Array(n).fill(0));
    for (let i = 0; i < s; i++) {
      let sr = i,
        sc = i;
      for (let j = 0; j < 4; j++) {
        while (sr === i && sc >= i && sc < n - 1 - i) {
          result[sr][sc + 1] = boards[startR + sr][startC + sc];
          sc++;
        }

        while (sr >= i && sr < n - 1 - i && sc === n - 1 - i) {
          result[sr + 1][sc] = boards[startR + sr][startC + sc];
          sr++;
        }

        while (sr === n - 1 - i && sc > i && sc <= n - 1 - i) {
          result[sr][sc - 1] = boards[startR + sr][startC + sc];
          sc--;
        }

        while (sr > i && sr <= n - 1 - i && sc === i) {
          result[sr - 1][sc] = boards[startR + sr][startC + sc];
          sr--;
        }
      }
    }
    result[s][s] = boards[startR + s][startC + s];

    for (let i = 0; i < n; i++) {
      for (let j = 0; j < n; j++) {
   		 boards[startR + i][startC + j] = result[i][j];
      }
    }
  }
}

const input = [];
require('readline')
  .createInterface(process.stdin, process.stdout)
  .on('line', (line) => {
    input.push(line);
  })
  .on('close', () => {
    console.log(sol(input));
    process.exit();
  });

 

풀이

 

문제를 해결하기 위한 절차를 파악하고, 사용할 함수를 구현해서 모두 테스트하면 쉽게 풀리는 문제다.

 

문제를 위해서는, 2가지 함수가 필요하다.

- 회전 연산의 순서를 정하는 함수

- 회전을 수행하는 함수

 

각각 하나씩 어떻게 구현할지 생각해보자.

 

회전 연산의 순서를 정하는 함수

회전 연산 갯수 K는 1~6까지의 정수다. 연산의 "순서"를 정해야 하므로 K개의 순열을 구한다.

간단하게 dfs를 통해서 순서 배열의 경우의 수를 구하고, 순서 배열의 원소의 개수가 K개일 때마다, 회전을 순서대로 수행하고 행 합계의 최솟값을 구하면 되겠다. 우리는 모든 경우의 수에 대해서 최솟값을 구해야 하므로 dfs를 끝까지 진행하면 되겠다.

 

 

회전을 수행하는 함수

(r,c) = 회전의 기준이 될 중앙 위치, s = 회전을 수행할 한쪽 크기이다.

(r-s, c-s)가 회전할 행렬의 왼쪽위 시작점이고, (r+s, c+s)가 회전할 행렬의 오른쪽 아래 끝점이다.

 

시계방향으로 1칸씩 이동

회전을 수행할 배열을 돌릴 때, 시계방향으로 1칸씩 돌린다.

 

회전할 배열은 2*s+1의 크기를 가지며, 항상 홀수개이고 s번 회전을 수행하면 된다.

그리고 마지막 (r,c)는 배열의 중앙이므로 회전의 대상이 되지 않는다.

그림과 같이 회전을 2번(= s) 수행하면 되겠다.

2회의 for문에서 윗변, 아랫변, 좌우측면 변을 이동시키는 4개의 연산을 수행하면 될 듯 하다.

이러쿵저러쿵해서 이동시킬 행과 열 위치를 기준으로 모두 이동시켜보자.

 

풀이

그래서, 회전연산 K개에 대해서 K! 개의 경우의 수를 구하고, 각 경우의 수마다 정해진 순서대로 회전연산을 수행한 결과 배열의 행의 합 최솟값을 갱신하면 정답을 구할 수 있다.


 

간단한 주석 첨부

function sol(input) {
  const [N, M, K] = input[0].split(' ').map(Number);
  let boards;
  let answer = Number.MAX_SAFE_INTEGER;
  const rotateOperations = input
    .slice(1 + N)
    .map((str) => str.split(' ').map(Number)); // 회전연산을 담아둔다.

  dfs(0, []);

  return answer;
	// 코드 실행은 여기서 끝난다. 밑에부터는 구현한 함수다.
    
  function dfs(L, orders) {
    if (orders.length === K) {
      boards = input.slice(1, 1 + N).map((row) => row.split(' ').map(Number));
	  // 경우의 수의 원소 갯수가 K개면 회전 연산을 수행할 것이므로, 배열 A를 복사한다.
      
      orders.forEach((order) =>
        rotate2DMatrixBy1Step(...rotateOperations[order])
      ); // 경우의수 orders의 원소를 순회하며 회전 연산을 수행한다.

      boards.forEach((row) => {
        const min = row.reduce((acc, val) => acc + val, 0);
        answer = Math.min(answer, min);
      }); // 배열 A의 행의 합 최솟값을 갱신한다.
      return;
    }

    for (let i = 0; i < K; i++) {
      if (orders.includes(i)) continue;
      dfs(L + 1, [...orders, i]);
    }
  }

  function rotate2DMatrixBy1Step(r, c, s) {
    const n = 2 * s + 1;
    const startR = r - s - 1;
    const startC = c - s - 1;
    // startR, startC는 배열A에서 회전을 시작할 행과 열이다.
	// 순서가 헷갈려서, 새로운 배열 result를 n*n 크기로 선언했다.
    // 여기에 회전 결과를 담아두고, board로 복사할 예정이다.
    
    const result = Array.from({ length: n }, () => new Array(n).fill(0));
    for (let i = 0; i < s; i++) {
      let sr = i,
        sc = i;
      // 회전 연산 당 s회만큼 반복해야 배열 내부를 모두 회전시킬 수 있다.
      // sr,sc는 시작할 지점이며, boards에서 실행해야 하므로 startR, startC와 연계한다.
      // 또한 result는 n*n크기이므로 (sr,sc)에 회전된 모습을 저장하게 된다.
      for (let j = 0; j < 4; j++) {
        while (sr === i && sc >= i && sc < n - 1 - i) {
          result[sr][sc + 1] = boards[startR + sr][startC + sc];
          sc++;
        } // 윗쪽 변 이동

        while (sr >= i && sr < n - 1 - i && sc === n - 1 - i) {
          result[sr + 1][sc] = boards[startR + sr][startC + sc];
          sr++;
        } // 오른쪽 변 이동

        while (sr === n - 1 - i && sc > i && sc <= n - 1 - i) {
          result[sr][sc - 1] = boards[startR + sr][startC + sc];
          sc--;
        } // 아랫 변 이동

        while (sr > i && sr <= n - 1 - i && sc === i) {
          result[sr - 1][sc] = boards[startR + sr][startC + sc];
          sr--;
        } // 왼쪽 변 이동
      }
    }
    result[s][s] = boards[startR + s][startC + s];
    // (r,c) 지점은 회전을 수행하지 않으므로 그대로 복사한다.

    for (let i = 0; i < n; i++) {
      for (let j = 0; j < n; j++) {
        boards[startR + i][startC + j] = result[i][j];
      }
    } // 회전 결과 배열을 boards 배열로 복사해주면 된다.
  }
}

const input = [];
require('readline')
  .createInterface(process.stdin, process.stdout)
  .on('line', (line) => {
    input.push(line);
  })
  .on('close', () => {
    console.log(sol(input));
    process.exit();
  });
저작자표시 (새창열림)

'DS & Algorithm > baekjoon' 카테고리의 다른 글

[백준] 25632번 소수부르기게임 - 자바스크립트  (0) 2022.09.27
[백준] 1753번 최단경로 - 자바스크립트  (0) 2022.09.22
[백준] 13460번 구슬 탈출 2 - 자바스크립트  (0) 2022.03.25
[백준] 1541번 잃어버린 괄호 - JavaScript(NodeJS)  (0) 2021.07.19
[백준] 2108번 통계학 - JavaScript(NodeJS)  (0) 2021.07.18
  • 문제
  • 코드
'DS & Algorithm/baekjoon' 카테고리의 다른 글
  • [백준] 25632번 소수부르기게임 - 자바스크립트
  • [백준] 1753번 최단경로 - 자바스크립트
  • [백준] 13460번 구슬 탈출 2 - 자바스크립트
  • [백준] 1541번 잃어버린 괄호 - JavaScript(NodeJS)
jiho_bae
jiho_bae
하루에 한 걸음씩

티스토리툴바

개인정보

  • 티스토리 홈
  • 포럼
  • 로그인

단축키

내 블로그

내 블로그 - 관리자 홈 전환
Q
Q
새 글 쓰기
W
W

블로그 게시글

글 수정 (권한 있는 경우)
E
E
댓글 영역으로 이동
C
C

모든 영역

이 페이지의 URL 복사
S
S
맨 위로 이동
T
T
티스토리 홈 이동
H
H
단축키 안내
Shift + /
⇧ + /

* 단축키는 한글/영문 대소문자로 이용 가능하며, 티스토리 기본 도메인에서만 동작합니다.