[백준] 2477 참외밭 JavaScript

·2024년 10월 15일

문제

시골에 있는 태양이의 삼촌 댁에는 커다란 참외밭이 있다. 문득 태양이는 이 밭에서 자라는 참외가 도대체 몇 개나 되는지 궁금해졌다. 어떻게 알아낼 수 있는지 골똘히 생각하다가 드디어 좋은 아이디어가 떠올랐다. 유레카! 1m2의 넓이에 자라는 참외 개수를 헤아린 다음, 참외밭의 넓이를 구하면 비례식을 이용하여 참외의 총개수를 구할 수 있다.

1m2의 넓이에 자라는 참외의 개수는 헤아렸고, 이제 참외밭의 넓이만 구하면 된다. 참외밭은 ㄱ-자 모양이거나 ㄱ-자를 90도, 180도, 270도 회전한 모양(┏, ┗, ┛ 모양)의 육각형이다. 다행히도 밭의 경계(육각형의 변)는 모두 동서 방향이거나 남북 방향이었다. 밭의 한 모퉁이에서 출발하여 밭의 둘레를 돌면서 밭경계 길이를 모두 측정하였다.

예를 들어 참외밭이 위 그림과 같은 모양이라고 하자. 그림에서 오른쪽은 동쪽, 왼쪽은 서쪽, 아래쪽은 남쪽, 위쪽은 북쪽이다. 이 그림의 왼쪽위 꼭짓점에서 출발하여, 반시계방향으로 남쪽으로 30m, 동쪽으로 60m, 남쪽으로 20m, 동쪽으로 100m, 북쪽으로 50m, 서쪽으로 160m 이동하면 다시 출발점으로 되돌아가게 된다.

위 그림의 참외밭 면적은 6800m^2이다. 만약 1m2의 넓이에 자라는 참외의 개수가 7이라면, 이 밭에서 자라는 참외의 개수는 47600으로 계산된다.

1m2의 넓이에 자라는 참외의 개수와, 참외밭을 이루는 육각형의 임의의 한 꼭짓점에서 출발하여 반시계방향으로 둘레를 돌면서 지나는 변의 방향과 길이가 순서대로 주어진다. 이 참외밭에서 자라는 참외의 수를 구하는 프로그램을 작성하시오.

입력

첫 번째 줄에 1m^2의 넓이에 자라는 참외의 개수를 나타내는 양의 정수 K (1 ≤ K ≤ 20)가 주어진다. 참외밭을 나타내는 육각형의 임의의 한 꼭짓점에서 출발하여 반시계방향으로 둘레를 돌면서 지나는 변의 방향과 길이 (1 이상 500 이하의 정수) 가 둘째 줄부터 일곱 번째 줄까지 한 줄에 하나씩 순서대로 주어진다. 변의 방향에서 동쪽은 1, 서쪽은 2, 남쪽은 3, 북쪽은 4로 나타낸다.

출력

첫째 줄에 입력으로 주어진 밭에서 자라는 참외의 수를 출력한다.

예제 입력

7
4 50
2 160
3 30
1 60
3 20
1 100

예제 출력

47600

내가 했던 풀이 방법


큰 사각형에서 작은 사각형을 빼주는 형태로 풀이했다. 나올 수 있는 모양을 모두 생각해봤을 때, 방향이 중복되지 않는 방향의 값들이 큰 사각형의 가로/세로가 될 것이다. set을 이용해서 중복되지 않는 방향을 찾고 해당 방향의 값을 곱해주어 큰 사각형의 넓이를 구한다.
set에 존재하는 값은 당연히 4가지 밖에 없다. 4가지 분기점을 두고 작은 사각형의 길이들을 찾아주면 된다. 하나의 예시를 들면, set에 존재하는 값이 [4, 1]일 때 예시의 문제가 될 것이다. 이때 1번부터 반시계 방향으로 방향만 생각하면 [1, 4, 2, 3, 2, 3]이 될 것이다. 여기서 굵게 표시된 곳이 우리가 찾는 작은 사각형의 길이들이 될 것이다. 어느 곳부터 입력됐을지는 알 수 없으므로 lengths를 합쳐주어 해당 경우가 무조건 존재하도록 해주어야 한다. 예를 들어 위와 같은 상황에서 [2, 3, 1, 4, 2, 3]이라면 while문으로 찾기가 까다롭다. 그러므로 lengths를 합쳐주어 찾는 결과가 무조건 존재하도록 해주어야 한다.

  1. set을 이용해 방향이 중복되지 않은 방향 2개를 찾아준다. 이를 찾아내 set에 들어있는 방향의 값 2개를 곱한 결과를 max에 저장한다.
  2. lengths를 2개 연달아 합쳐준다.
  3. set에 존재하는 값을 분기점으로 나누고, 그에 맞춰서 lengths에서 연달아 나오는 방향이 찾는 방향과 일치할 때까지 current를 증가시키고 나온 current의 값과 그 다음 값을 곱한 결과를 min에 저장해준다.
  4. max와 min을 빼준 값에 K를 곱한 값을 출력해준다.

코드

const fs = require('fs');
let [K, ...lengths] = fs.readFileSync(0, 'utf-8').toString().trim().split('\n');

K = Number(K);
for (let i = 0; i < lengths.length; i++) {
  lengths[i] = lengths[i].trim().split(' ').map(Number);
}

let set = new Set();
for (let i = 0; i < lengths.length; i++) {
  if (set.has(lengths[i][0])) set.delete(lengths[i][0]);
  else set.add(lengths[i][0]);
}

let max = 1;
for (let i = 0; i < lengths.length; i++) {
  if (set.has(lengths[i][0])) {
    max *= lengths[i][1];
  }
}

lengths = lengths.concat(lengths);
let min = 0;
if (set.has(4) && set.has(1)) {
  let current = 0;
  while (true) {
    if (lengths[current][0] === 3 && lengths[current + 1][0] === 2) break;
    current++;
  }
  min = lengths[current][1] * lengths[current + 1][1];
} else if (set.has(1) && set.has(3)) {
  let current = 0;
  while (true) {
    if (lengths[current][0] === 2 && lengths[current + 1][0] === 4) break;
    current++;
  }
  min = lengths[current][1] * lengths[current + 1][1];
} else if (set.has(2) && set.has(4)) {
  let current = 0;
  while (true) {
    if (lengths[current][0] === 1 && lengths[current + 1][0] === 3) break;
    current++;
  }
  min = lengths[current][1] * lengths[current + 1][1];
} else {
  let current = 0;
  while (true) {
    if (lengths[current][0] === 4 && lengths[current + 1][0] === 1) break;
    current++;
  }
  min = lengths[current][1] * lengths[current + 1][1];
}

console.log((max - min) * K);

회고

좀 더 효율적으로 코드가 있는 것 같기는 한데 도저히 생각이 안나기도 하고 나오는 경우가 무조건 4개이기 때문에 해당 방법으로도 충분히 풀이할 수 있을 것 같았다..

profile
Frontend🍓

0개의 댓글