https://www.acmicpc.net/problem/2485

 

2485번: 가로수

첫째 줄에는 이미 심어져 있는 가로수의 수를 나타내는 하나의 정수 N이 주어진다(3 ≤ N ≤ 100,000). 둘째 줄부터 N개의 줄에는 각 줄마다 심어져 있는 가로수의 위치가 양의 정수로 주어지며, 가

www.acmicpc.net

문제

직선으로 되어있는 도로의 한 편에 가로수가 임의의 간격으로 심어져있다. KOI 시에서는 가로수들이 모두 같은 간격이 되도록 가로수를 추가로 심는 사업을 추진하고 있다. KOI 시에서는 예산문제로 가능한 한 가장 적은 수의 나무를 심고 싶다.

편의상 가로수의 위치는 기준점으로 부터 떨어져 있는 거리로 표현되며, 가로수의 위치는 모두 양의 정수이다.

예를 들어, 가로수가 (1, 3, 7, 13)의 위치에 있다면 (5, 9, 11)의 위치에 가로수를 더 심으면 모든 가로수들의 간격이 같게 된다. 또한, 가로수가 (2, 6, 12, 18)에 있다면 (4, 8, 10, 14, 16)에 가로수를 더 심어야 한다.

심어져 있는 가로수의 위치가 주어질 때, 모든 가로수가 같은 간격이 되도록 새로 심어야 하는 가로수의 최소수를 구하는 프로그램을 작성하라. 단, 추가되는 나무는 기존의 나무들 사이에만 심을 수 있다.

입력

첫째 줄에는 이미 심어져 있는 가로수의 수를 나타내는 하나의 정수 N이 주어진다(3 ≤ N ≤ 100,000). 둘째 줄부터 N개의 줄에는 각 줄마다 심어져 있는 가로수의 위치가 양의 정수로 주어지며, 가로수의 위치를 나타내는 정수는 1,000,000,000 이하이다. 가로수의 위치를 나타내는 정수는 모두 다르고, N개의 가로수는 기준점으로부터 떨어진 거리가 가까운 순서대로 주어진다.

출력

모든 가로수가 같은 간격이 되도록 새로 심어야 하는 가로수의 최소수를 첫 번째 줄에 출력한다.

예제 입력 1 복사

4
1
3
7
13

예제 출력 1 복사

3

예제 입력 2 복사

4
2
6
12
18

예제 출력 2 복사

5

 

문제풀이(1) - 72%에서 실패

임의로 세우진 간격 사이에 최소한의 가로수를 일정한 간격으로 심었을 때 가로수의 개수를 출력하는 문제이다.
가로수 간의 간격을 구한다음에 간격들의 최대공약수를 구한뒤 일정한 간격으로 세워지지 않은 간격을 찾아서 최대공약수 마다 나무를 심어주면된다.

const filePath = process.platform === "linux" ? "/dev/stdin" : "./input.txt";
const [N, ...arr] = require("fs").readFileSync(filePath).toString().trim().split("\n").map(Number);

const interval = [];

let answer = 0;

for (let i = 0; i < N - 1; i++) {
  interval[i] = Math.abs(arr[i] - arr[i + 1]);
}

// 유클리드 호제법 최대공약수 구하기
const getGcd = (a, b) => {
  if (a % b === 0) {
    return b;
  }
  return getGcd(b, a % b);
};

let gcd = interval[0];

for (let i = 0; i < N - 2; i++) {
  let temp = getGcd(interval[i + 1], interval[i]);
  if (temp < gcd) gcd = temp;
}

for (let i = 0; i < N - 1; i++) {
  const temp = interval[i];

  if (temp !== gcd) {
    answer += temp / gcd - 1;
  }
}

console.log(answer);

 

문제풀이(2) - 성공

문제풀이(1)에서 최대공약수를 잘 못 구하고 있었다. 해당 부분을 확인하여 수정하여 통과하였다.

const filePath = process.platform === "linux" ? "/dev/stdin" : "./input.txt";
const [N, ...arr] = require("fs").readFileSync(filePath).toString().trim().split("\n").map(Number);

const interval = [];

let answer = 0;

for (let i = 1; i < N; i++) {
  interval[i - 1] = arr[i] - arr[i - 1];
}

// 유클리드 호제법 최대공약수 구하기
const getGcd = (a, b) => {
  if (b === 0) {
    return a;
  }
  return getGcd(b, a % b);
};

let gcd = interval[0];

for (let i = 1; i < N - 1; i++) {
  gcd = getGcd(gcd, interval[i]);
}

interval.forEach((value) => {
  answer += value / gcd - 1;
});

console.log(answer);

https://www.acmicpc.net/problem/2578

 

2578번: 빙고

첫째 줄부터 다섯째 줄까지 빙고판에 쓰여진 수가 가장 위 가로줄부터 차례대로 한 줄에 다섯 개씩 빈 칸을 사이에 두고 주어진다. 여섯째 줄부터 열째 줄까지 사회자가 부르는 수가 차례대로

www.acmicpc.net

문제

빙고 게임은 다음과 같은 방식으로 이루어진다.

먼저 아래와 같이 25개의 칸으로 이루어진 빙고판에 1부터 25까지 자연수를 한 칸에 하나씩 쓴다

 

다음은 사회자가 부르는 수를 차례로 지워나간다. 예를 들어 5, 10, 7이 불렸다면 이 세 수를 지운 뒤 빙고판의 모습은 다음과 같다.

 

차례로 수를 지워가다가 같은 가로줄, 세로줄 또는 대각선 위에 있는 5개의 모든 수가 지워지는 경우 그 줄에 선을 긋는다.

 

이러한 선이 세 개 이상 그어지는 순간 "빙고"라고 외치는데, 가장 먼저 외치는 사람이 게임의 승자가 된다.

 

철수는 친구들과 빙고 게임을 하고 있다. 철수가 빙고판에 쓴 수들과 사회자가 부르는 수의 순서가 주어질 때, 사회자가 몇 번째 수를 부른 후 철수가 "빙고"를 외치게 되는지를 출력하는 프로그램을 작성하시오.

입력

첫째 줄부터 다섯째 줄까지 빙고판에 쓰여진 수가 가장 위 가로줄부터 차례대로 한 줄에 다섯 개씩 빈 칸을 사이에 두고 주어진다. 여섯째 줄부터 열째 줄까지 사회자가 부르는 수가 차례대로 한 줄에 다섯 개씩 빈 칸을 사이에 두고 주어진다. 빙고판에 쓰여진 수와 사회자가 부르는 수는 각각 1부터 25까지의 수가 한 번씩 사용된다.

출력

첫째 줄에 사회자가 몇 번째 수를 부른 후 철수가 "빙고"를 외치게 되는지 출력한다.

예제 입력 1 복사

11 12 2 24 10
16 1 13 3 25
6 20 5 21 17
19 4 8 14 9
22 15 7 23 18
5 10 7 16 2
4 22 8 17 13
3 18 1 6 25
12 19 23 14 21
11 24 9 20 15

예제 출력 1 복사

15

 

문제풀이(1)

사회자가 부르는 수의 순서에 맞게 철수의 빙고판에 'O'로 변경한다.
빙고가 3개가 되는 시점이 사회자가 몇번 수를 불렀는지를 판단하는 로직을 구현한다.
사회자가 수를 불러서 철수의 빙고판에 칠하는 로직과 빙고 여부를 알 수 있는 로직을 구현한다.

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

const chulsoo = input.slice(0, 5).map((numbers) => numbers.split(" ").map(Number));
const moderator = input.slice(5).map((numbers) => numbers.split(" ").map(Number));

const N = 5;

let answer = 0;

// 빙고판 숫자 색칠하기
const bingoPainting = (targetNum) => {
  for (let i = 0; i < N; i++) {
    for (let j = 0; j < N; j++) {
      if (chulsoo[i][j] === targetNum) {
        chulsoo[i][j] = "O";
      }
    }
  }
};

// 빙고 확인하기
const bingoCheck = () => {
  let totalBingoCount = 0;
  // 가로줄 빙고 확인
  for (let x = 0; x < N; x++) {
    if (chulsoo[x].filter((x) => x === "O").length === 5) {
      totalBingoCount++;
    }
  }

  // 세로줄 빙고 확인
  for (let x = 0; x < N; x++) {
    let yBingoCount = 0;
    for (let y = 0; y < N; y++) {
      if (chulsoo[y][x] === "O") {
        yBingoCount++;
      }
    }
    if (yBingoCount === 5) {
      totalBingoCount++;
    }
  }

  // 대각선 빙고 확인(대각선인 경우는 엑스자 일 경우 밖에 없기 때문에 2번만 확인하면 됨)
  // [[0,0], [1,1], [2,2], [3,3], [4,4]]
  // [[0,4], [1,3], [2,2], [3,1], [4,0]]
  let leftDiagonalBingoCount = 0;
  let rightDiagonalBingoCount = 0;
  for (let i = 0; i < N; i++) {
    if (chulsoo[i][i] === "O") {
      leftDiagonalBingoCount++;
    }

    if (chulsoo[i][N - 1 - i] === "O") {
      rightDiagonalBingoCount++;
    }
  }

  if (leftDiagonalBingoCount === N) {
    totalBingoCount++;
  }

  if (rightDiagonalBingoCount === N) {
    totalBingoCount++;
  }

  return totalBingoCount;
};

for (let i = 0; i < N; i++) {
  let bingoCount = 0;
  for (let j = 0; j < N; j++) {
    answer++;
    bingoPainting(moderator[i][j]);
    bingoCount = bingoCheck();
    if (bingoCount >= 3) {
      break;
    }
  }

  if (bingoCount >= 3) {
    break;
  }
}

console.log(answer);

 

문제풀이(2) - 리팩토링

1. 중복된 코드 최소화
2. 빙고확인할 때 every 메서드 사용
3. for문 중단문 2개를 process.exit(0);를 사용하여 종료

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

const chulsoo = input.slice(0, 5).map((numbers) => numbers.split(" ").map(Number));
const moderator = input.slice(5).map((numbers) => numbers.split(" ").map(Number));

const N = 5;

let answer = 0;

// 빙고판 숫자 색칠하기
const bingoPainting = (targetNum) => {
  for (let i = 0; i < N; i++) {
    for (let j = 0; j < N; j++) {
      if (chulsoo[i][j] === targetNum) {
        chulsoo[i][j] = "O";
      }
    }
  }
};

// 빙고 확인하기
const bingoCheck = () => {
  let count = 0;

  // 가로, 세로, 대각선 빙고 확인
  for (let i = 0; i < N; i++) {
    if (chulsoo[i].every((val) => val === "O")) count++; // 가로 빙고 확인
    if (chulsoo.every((row) => row[i] === "O")) count++; // 세로 빙고 확인
  }

  // 대각선 빙고 확인
  if (chulsoo.every((row, idx) => row[idx] === "O")) count++;
  if (chulsoo.every((row, idx) => row[N - idx - 1] === "O")) count++;

  return count;
};

for (let i = 0; i < N; i++) {
  for (let j = 0; j < N; j++) {
    answer++;
    bingoPainting(moderator[i][j]);
    if (bingoCheck() >= 3) {
      console.log(answer);
      process.exit(0);
    }
  }
}

https://www.acmicpc.net/problem/2847

 

2847번: 게임을 만든 동준이

학교에서 그래픽스 수업을 들은 동준이는 수업시간에 들은 내용을 바탕으로 스마트폰 게임을 만들었다. 게임에는 총 N개의 레벨이 있고, 각 레벨을 클리어할 때 마다 점수가 주어진다. 플레이어

www.acmicpc.net

문제

학교에서 그래픽스 수업을 들은 동준이는 수업시간에 들은 내용을 바탕으로 스마트폰 게임을 만들었다. 게임에는 총 N개의 레벨이 있고, 각 레벨을 클리어할 때 마다 점수가 주어진다. 플레이어의 점수는 레벨을 클리어하면서 얻은 점수의 합으로, 이 점수를 바탕으로 온라인 순위를 매긴다. 동준이는 레벨을 난이도 순으로 배치했다. 하지만, 실수로 쉬운 레벨이 어려운 레벨보다 점수를 많이 받는 경우를 만들었다.

이 문제를 해결하기 위해 동준이는 특정 레벨의 점수를 감소시키려고 한다. 이렇게해서 각 레벨을 클리어할 때 주는 점수가 증가하게 만들려고 한다.

각 레벨을 클리어할 때 얻는 점수가 주어졌을 때, 몇 번 감소시키면 되는지 구하는 프로그램을 작성하시오. 점수는 항상 양수이어야 하고, 1만큼 감소시키는 것이 1번이다. 항상 답이 존재하는 경우만 주어진다. 정답이 여러 가지인 경우에는 점수를 내리는 것을 최소한으로 하는 방법을 찾아야 한다.

입력

첫째 줄에 레벨의 수 N이 주어진다. (1 ≤ N ≤ 100) 다음 N개 줄에는 각 레벨을 클리어하면 얻는 점수가 첫 번째 레벨부터 마지막 레벨까지 순서대로 주어진다. 점수는 20,000보다 작은 양의 정수이다.

출력

첫째 줄에 점수를 몇 번 감소시키면 되는지 출력한다.

예제 입력 1 복사

3
5
5
5

예제 출력 1 복사

3

 

문제풀이(1)

레벨을 클리어 할 떄마다 주어지는 점수를 배열에 넣고, 뒤에서 부터 순회하면서 arr[i-1]이 arr[i] 값보다 크거나 같다면 arr[i-1]을 arr[i]보다 1작게 한다.

const filePath = process.platform === "linux" ? "/dev/stdin" : "./input.txt";
const [N, ...arr] = require("fs").readFileSync(filePath).toString().trim().split("\n").map(Number);

let answer = 0;

for (let i = N - 1; i > 0; i--) {
  if (arr[i - 1] >= arr[i]) {
    answer += arr[i - 1] - arr[i] + 1;
    arr[i - 1] = arr[i] - 1;
  }
}

console.log(answer);

https://www.acmicpc.net/problem/1015

 

1015번: 수열 정렬

P[0], P[1], ...., P[N-1]은 0부터 N-1까지(포함)의 수를 한 번씩 포함하고 있는 수열이다. 수열 P를 길이가 N인 배열 A에 적용하면 길이가 N인 배열 B가 된다. 적용하는 방법은 B[P[i]] = A[i]이다. 배열 A가 주

www.acmicpc.net

문제

P[0], P[1], ...., P[N-1]은 0부터 N-1까지(포함)의 수를 한 번씩 포함하고 있는 수열이다. 수열 P를 길이가 N인 배열 A에 적용하면 길이가 N인 배열 B가 된다. 적용하는 방법은 B[P[i]] = A[i]이다.

배열 A가 주어졌을 때, 수열 P를 적용한 결과가 비내림차순이 되는 수열을 찾는 프로그램을 작성하시오. 비내림차순이란, 각각의 원소가 바로 앞에 있는 원소보다 크거나 같을 경우를 말한다. 만약 그러한 수열이 여러개라면 사전순으로 앞서는 것을 출력한다.

입력

첫째 줄에 배열 A의 크기 N이 주어진다. 둘째 줄에는 배열 A의 원소가 0번부터 차례대로 주어진다. N은 50보다 작거나 같은 자연수이고, 배열의 원소는 1,000보다 작거나 같은 자연수이다.

출력

첫째 줄에 비내림차순으로 만드는 수열 P를 출력한다.

예제 입력 1 복사

3
2 3 1

예제 출력 1 복사

1 2 0

 

문제풀이(1)

주어진 수들을 비내림차순 즉 오름차순으로 만드는 수열을 만들면 되는 문제이다.
A배열을 오름차순으로 정렬한 것과 정렬하지 않은 기본의 A배열을 가지고 비교하면된다.

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

const N = Number(input[0]);
const A = input[1].split(" ").map(Number);
const sortedA = input[1]
  .split(" ")
  .map(Number)
  .sort((a, b) => a - b);

const P = Array(N).fill(-1);

A.forEach((num, idx) => {
  P[idx] = sortedA.findIndex((sortedNum, sortedNumIdx) => {
    if (sortedNum === num && !P.includes(sortedNumIdx)) return true;
  });
});

console.log(P.join(' '));

 

문제풀이(2) - 리팩토링

1. 가속성 향상을 위한 변수명 변경
2. Array.prototype.map 과 Array.prototype.indexOf 를 사용하여 코드를 간결하게 작성

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

const originalArray = input[1].split(" ").map(Number);
const sortedArray = [...originalArray].sort((a, b) => a - b);

const positionInSortedArray = originalArray.map((num) => {
  const position = sortedArray.indexOf(num);
  sortedArray[position] = null; // 이 위치의 값을 null로 변경하여 더 이상 선택되지 않게 한다.
  return position;
});

console.log(positionInSortedArray.join(' '));

https://www.acmicpc.net/problem/9656

 

9656번: 돌 게임 2

상근이가 게임을 이기면 SK를, 창영이가 게임을 이기면 CY을 출력한다.

www.acmicpc.net

문제

돌 게임은 두 명이서 즐기는 재밌는 게임이다.

탁자 위에 돌 N개가 있다. 상근이와 창영이는 턴을 번갈아가면서 돌을 가져가며, 돌은 1개 또는 3개 가져갈 수 있다. 마지막 돌을 가져가는 사람이 게임을 지게 된다.

두 사람이 완벽하게 게임을 했을 때, 이기는 사람을 구하는 프로그램을 작성하시오. 게임은 상근이가 먼저 시작한다.

입력

첫째 줄에 N이 주어진다. (1 ≤ N ≤ 1000)

출력

상근이가 게임을 이기면 SK를, 창영이가 게임을 이기면 CY을 출력한다.

예제 입력 1 복사

4

예제 출력 1 복사

SK

 

문제풀이(1)

실버4에서 문제가 이렇게 간단하게 나온건 처음인것 같다.
2명이 게임을 하고 있을 떄 하나씩 돌을 번갈아 가면서 갖게 되고, 상근이가 이기면 SK, 창영이가 이기면 CY를 출력하면 되는 문제이다.
주어진 수를 2로 나눠서 나머지가 있다면 CY를 없다면 SK를 출력한다.

const filePath = process.platform === "linux" ? "/dev/stdin" : "./input.txt";
const N = Number(require("fs").readFileSync(filePath).toString().trim());

if (N % 2) {
  console.log("CY");
} else {
  console.log("SK");
}

https://www.acmicpc.net/problem/1940

 

1940번: 주몽

첫째 줄에는 재료의 개수 N(1 ≤ N ≤ 15,000)이 주어진다. 그리고 두 번째 줄에는 갑옷을 만드는데 필요한 수 M(1 ≤ M ≤ 10,000,000) 주어진다. 그리고 마지막으로 셋째 줄에는 N개의 재료들이 가진 고

www.acmicpc.net

문제

주몽은 철기군을 양성하기 위한 프로젝트에 나섰다. 그래서 야철대장을 통해 철기군이 입을 갑옷을 만들게 하였다. 야철대장은 주몽의 명에 따르기 위하여 연구에 착수하던 중 아래와 같은 사실을 발견하게 되었다.

갑옷을 만드는 재료들은 각각 고유한 번호를 가지고 있다. 갑옷은 두 개의 재료로 만드는데 두 재료의 고유한 번호를 합쳐서 M(1 ≤ M ≤ 10,000,000)이 되면 갑옷이 만들어 지게 된다. 야철대장은 자신이 만들고 있는 재료를 가지고 갑옷을 몇 개나 만들 수 있는지 궁금해졌다. 이러한 궁금증을 풀어 주기 위하여 N(1 ≤ N ≤ 15,000) 개의 재료와 M이 주어졌을 때 몇 개의 갑옷을 만들 수 있는지를 구하는 프로그램을 작성하시오.

입력

첫째 줄에는 재료의 개수 N(1 ≤ N ≤ 15,000)이 주어진다. 그리고 두 번째 줄에는 갑옷을 만드는데 필요한 수 M(1 ≤ M ≤ 10,000,000) 주어진다. 그리고 마지막으로 셋째 줄에는 N개의 재료들이 가진 고유한 번호들이 공백을 사이에 두고 주어진다. 고유한 번호는 100,000보다 작거나 같은 자연수이다.

출력

첫째 줄에 갑옷을 만들 수 있는 개수를 출력한다.

예제 입력 1 복사

6
9
2 7 4 1 5 3

예제 출력 1 복사

2

 

문제풀이(1)

주어진 수가 될 수 있도록 2가지의 수를 조합하여 주어진 수가 될 수 있도록 맞추는 문제이다.
오름차순으로 수를 정렬하여 제일 작은 값과 제일 큰 값을 합한 수가 맞는지 확인한다.
더한수가 주어진 수(M)보다 작다면 다음으로 작은수를 찾아서 더하고, 크다면 다음으로 큰 수를 찾아서 더한다.

const filePath = process.platform === "linux" ? "/dev/stdin" : "./input.txt";
const [N, M, ...arr] = require("fs").readFileSync(filePath).toString().trim().split("\n");

const numbers = arr[0]
  .split(" ")
  .map(Number)
  .sort((a, b) => a - b);

let answer = 0;

let left = 0;
let right = Number(N) - 1;

while (left < right) {
  const sum = numbers[left] + numbers[right];

  if (sum === Number(M)) answer++;
  sum <= Number(M) ? left++ : right--;
}

console.log(answer);

+ Recent posts