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

 

28279번: 덱 2

첫째 줄에 명령의 수 N이 주어진다. (1 ≤ N ≤ 1,000,000) 둘째 줄부터 N개 줄에 명령이 하나씩 주어진다. 출력을 요구하는 명령은 하나 이상 주어진다.

www.acmicpc.net

문제

정수를 저장하는 덱을 구현한 다음, 입력으로 주어지는 명령을 처리하는 프로그램을 작성하시오.

명령은 총 여덟 가지이다.

  1. 1 X: 정수 X를 덱의 앞에 넣는다. (1 ≤ X ≤ 100,000)
  2. 2 X: 정수 X를 덱의 뒤에 넣는다. (1 ≤ X ≤ 100,000)
  3. 3: 덱에 정수가 있다면 맨 앞의 정수를 빼고 출력한다. 없다면 -1을 대신 출력한다.
  4. 4: 덱에 정수가 있다면 맨 뒤의 정수를 빼고 출력한다. 없다면 -1을 대신 출력한다.
  5. 5: 덱에 들어있는 정수의 개수를 출력한다.
  6. 6: 덱이 비어있으면 1, 아니면 0을 출력한다.
  7. 7: 덱에 정수가 있다면 맨 앞의 정수를 출력한다. 없다면 -1을 대신 출력한다.
  8. 8: 덱에 정수가 있다면 맨 뒤의 정수를 출력한다. 없다면 -1을 대신 출력한다.

입력

첫째 줄에 명령의 수 N이 주어진다. (1 ≤ N ≤ 1,000,000)

둘째 줄부터 N개 줄에 명령이 하나씩 주어진다.

출력을 요구하는 명령은 하나 이상 주어진다.

출력

출력을 요구하는 명령이 주어질 때마다 명령의 결과를 한 줄에 하나씩 출력한다.

예제 입력 1 복사

11
6
1 3
1 8
7
8
3
2 5
1 2
5
4
4

예제 출력 1 복사

1
8
3
8
3
5
3

 

문제풀이(1)

위의 데크로직을 구현하면 되는 문제이다. 시간이 다소 소요됐다.

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

class Node {
  constructor(value) {
    this.value = value;
    this.prev = null;
    this.next = null;
  }
}

class Deque {
  constructor() {
    this.head = null;
    this.tail = null;
    this.size = 0;
  }

  unshift(value) {
    // 정수 X를 덱의 앞에 넣는다.
    const node = new Node(value);
    if (!this.head) {
      this.tail = node;
    } else {
      node.next = this.head;
      this.head.prev = node;
    }
    this.head = node;
    this.size++;
  }

  push(value) {
    // 정수 X를 덱의 뒤에 넣는다.
    const node = new Node(value);
    if (!this.tail) {
      this.head = node;
    } else {
      node.prev = this.tail;
      this.tail.next = node;
    }
    this.tail = node;
    this.size++;
  }

  shift() {
    // 맨 앞의 정수를 빼고 출력한다.
    if (!this.head) {
      return -1;
    }
    const value = this.head.value;
    this.head = this.head.next;
    if (this.head) {
      this.head.prev = null;
    } else {
      this.tail = null;
    }
    this.size--;
    return value;
  }

  pop() {
    // 맨 뒤의 정수를 빼고 출력한다.
    if (!this.tail) {
      return -1;
    }
    const value = this.tail.value;
    this.tail = this.tail.prev;
    if (this.tail) {
      this.tail.next = null;
    } else {
      this.head = null;
    }
    this.size--;
    return value;
  }

  length() {
    // 덱에 들어있는 정수의 개수를 출력한다.
    return this.size;
  }

  isEmpty() {
    // 덱이 비어있으면 1, 아니면 0을 출력한다.
    return this.size === 0 ? 1 : 0;
  }

  getFront() {
    // 덱에 정수가 있다면 맨 앞의 정수를 출력한다.
    return this.head ? this.head.value : -1;
  }

  getBack() {
    // 덱에 정수가 있다면 맨 뒤의 정수를 출력한다.
    return this.tail ? this.tail.value : -1;
  }
}

const deque = new Deque();

let answer = "";

for (let i = 0; i < N; i++) {
  const [command, value] = input[i].split(" ").map(Number);

  // unshift, push, shift, pop, length, isEmpty, getFront, getBack
  switch (command) {
    case 1:
      deque.unshift(value);
      break;
    case 2:
      deque.push(value);
      break;
    case 3:
      answer += `${deque.shift()}\n`;
      break;
    case 4:
      answer += `${deque.pop()}\n`;
      break;
    case 5:
      answer += `${deque.length()}\n`;
      break;
    case 6:
      answer += `${deque.isEmpty()}\n`;
      break;
    case 7:
      answer += `${deque.getFront()}\n`;
      break;
    case 8:
      answer += `${deque.getBack()}\n`;
      break;
    default:
      break;
  }
}

console.log(answer.trim());

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

 

15649번: N과 M (1)

한 줄에 하나씩 문제의 조건을 만족하는 수열을 출력한다. 중복되는 수열을 여러 번 출력하면 안되며, 각 수열은 공백으로 구분해서 출력해야 한다. 수열은 사전 순으로 증가하는 순서로 출력해

www.acmicpc.net

문제

자연수 N과 M이 주어졌을 때, 아래 조건을 만족하는 길이가 M인 수열을 모두 구하는 프로그램을 작성하시오.

  • 1부터 N까지 자연수 중에서 중복 없이 M개를 고른 수열

입력

첫째 줄에 자연수 N과 M이 주어진다. (1 ≤ M ≤ N ≤ 8)

출력

한 줄에 하나씩 문제의 조건을 만족하는 수열을 출력한다. 중복되는 수열을 여러 번 출력하면 안되며, 각 수열은 공백으로 구분해서 출력해야 한다.

수열은 사전 순으로 증가하는 순서로 출력해야 한다.

예제 입력 1 복사

3 1

예제 출력 1 복사

1
2
3

예제 입력 2 복사

4 2

예제 출력 2 복사

1 2
1 3
1 4
2 1
2 3
2 4
3 1
3 2
3 4
4 1
4 2
4 3

 

문제풀이(1)

자신과 같거나 방문했던 노드는 선택하지 않는 점에서 DFS로 풀어야 한다고 생각했다.
찾아보니 이와 같은 문제를 백트래킹 문제라고 한다.

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

let result = "";
const answer = [];
const visited = new Array(N).fill(false);

const dfs = (count) => {
  if (count === M) {
    return (result += `${answer.join(" ")}\n`);
  }

  for (let i = 0; i < N; i++) {
    if (!visited[i]) {
      visited[i] = true;
      answer.push(i + 1);
      dfs(count + 1);
      answer.pop();
      visited[i] = false;
    }
  }
};

dfs(0);

console.log(result.trim());

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

 

2417번: 정수 제곱근

정수가 주어지면, 그 수의 정수 제곱근을 구하는 프로그램을 작성하시오.

www.acmicpc.net

문제

정수가 주어지면, 그 수의 정수 제곱근을 구하는 프로그램을 작성하시오.

입력

첫째 줄에 정수 n이 주어진다. (0 ≤ n < 2^63)

출력

첫째 줄에 q2 ≥ n인 가장 작은 음이 아닌 정수 q를 출력한다.

예제 입력 1 복사

122333444455555

예제 출력 1 복사

11060446

 

문제풀이(1)

처음엔 간단하게 Math.sqrt를 사용해서 제곱근을 구하면 될 것이라 생각해서 풀어보았다.

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

// 제곱근을 찾는다.
let result = Math.floor(Math.sqrt(n));

// 제곱근보다 작을 경우 +1을 해준다.
console.log(result ** 2 < n ? result + 1 : result);

 

문제풀이(2)

이진 탐색으로 푸는 방법이 있다고하여 구현해보았다.

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

const binarySearch = (num) => {
  let low = 0;
  let high = num;
  while (low <= high) {
    let mid = Math.floor((low + high) / 2);
    if (mid * mid < num) {
      low = mid + 1;
    } else {
      high = mid - 1;
    }
  }

  return low;
};

console.log(binarySearch(n));

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

 

1463번: 1로 만들기

첫째 줄에 1보다 크거나 같고, 106보다 작거나 같은 정수 N이 주어진다.

www.acmicpc.net

문제

정수 X에 사용할 수 있는 연산은 다음과 같이 세 가지 이다.

  1. X가 3으로 나누어 떨어지면, 3으로 나눈다.
  2. X가 2로 나누어 떨어지면, 2로 나눈다.
  3. 1을 뺀다.

정수 N이 주어졌을 때, 위와 같은 연산 세 개를 적절히 사용해서 1을 만들려고 한다. 연산을 사용하는 횟수의 최솟값을 출력하시오.

입력

첫째 줄에 1보다 크거나 같고, 106보다 작거나 같은 정수 N이 주어진다.

출력

첫째 줄에 연산을 하는 횟수의 최솟값을 출력한다.

예제 입력 1 복사

2

예제 출력 1 복사

1

예제 입력 2 복사

10

예제 출력 2 복사

3

 

문제풀이(1)

1. X가 3으로 나누어 떨어지면, 3으로 나눈다.
2. X가 2로 나누어 떨어지면, 2로 나눈다.
3. 1을 뺀다.
위의 공식을 실행하면 된다. 횟수를 카운트해서 출력한다.
하지만, 10^6승의 수가 나왔을 경우 연산횟수가 많아 질 수 있기 때문에 dp로 이전 값을 가져와서 계산하는 방법을 사용했다.

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

const dp = new Array(num + 1).fill(0);

for (let i = 2; i <= num; i++) {
  dp[i] = dp[i - 1] + 1;

  if (i % 2 === 0) {
    dp[i] = Math.min(dp[i], dp[i / 2] + 1);
  }

  if (i % 3 === 0) {
    dp[i] = Math.min(dp[i], dp[i / 3] + 1);
  }
}

console.log(dp[num]);

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

 

1246번: 온라인 판매

첫째 줄에 정수 N(1 ≤ N ≤ 1,000)과 M(1 ≤ M ≤ 1,000)이 입력된다. 둘째 줄부터 M+1번째 줄까지 i+1번째 줄에는 Pi(1 ≤ Pi ≤ 1,000,000)가 입력된다.

www.acmicpc.net

문제

경래는 닭을 기르는데 올 겨울 달걀 풍년으로 함박 웃음을 짓고 있다. 그리고 이 달걀을 영양란으로 둔갑하여 옥션에 판매하려한다.

경래는 총 N개의 달걀이 있고, 그의 잠재적인 고객은 총 M명이다. 그리고 각각의 i번째 고객은 각자 달걀 하나를 Pi 가격 이하로 살 수 있다고 밝혔다.

경래는 영양란이라 속인 죄책감에 한 고객에게 두 개 이상의 달걀은 팔지 않기로 하였다. 하지만 위의 규칙 하에 수익은 최대로 올리고 싶기에 얼마로 팔지 고민하고 있다. 즉, A가격에 달걀을 판다고 하면 Pi가 A가격보다 크거나 같은 모든 고객은 달걀을 산다는 뜻이다. (물론 달걀 총 수량을 초과하여 팔 수 는 없다)

문제는 이러한 경래를 도와 최대 수익을 올릴 수 있는 달걀의 가장 낮은 가격을 책정하는 것이다.

입력

첫째 줄에 정수 N(1 ≤ N ≤ 1,000)과 M(1 ≤ M ≤ 1,000)이 입력된다. 둘째 줄부터 M+1번째 줄까지 i+1번째 줄에는 Pi(1 ≤ Pi ≤ 1,000,000)가 입력된다.

출력

첫째 줄에 경래가 책정한 가격과 이 가격으로 올릴 수 있는 수익을 출력한다.

예제 입력 1 복사

5 4
2
8
10
7

예제 출력 1 복사

7 21

 

문제풀이(1)

내림차순으로 정렬해서 최대수익과 달걀가격을 구하면 된다. 이때, 최대수익은 i + 1 * arr[i]이고, 달걀의 가격은 arr[i]이다.

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

const [N, M] = input.shift().split(" ").map(Number);
const arr = input.map(Number);
arr.sort((a, b) => b - a);

const answer = [];

for (let i = 0; i < arr.length; i++) {
  if (i + 1 > N) {
    break;
  }

  // total - 최대 수익, value - 달걀 가격
  answer.push({ total: (i + 1) * arr[i], value: arr[i] });
}

answer.sort((a, b) => b.total - a.total);

console.log(answer[0].value, answer[0].total);

 

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

 

14469번: 소가 길을 건너간 이유 3

이웃 농장의 소가 길을 마구잡이로 건너는 것에 진절머리가 난 존은 극단의 결정을 내린다. 농장 둘레에 매우 큰 울타리를 짓는 것이다. 이렇게 하면 근처 농장 출신의 소가 들어올 일이 거의 없

www.acmicpc.net

문제

이웃 농장의 소가 길을 마구잡이로 건너는 것에 진절머리가 난 존은 극단의 결정을 내린다. 농장 둘레에 매우 큰 울타리를 짓는 것이다. 이렇게 하면 근처 농장 출신의 소가 들어올 일이 거의 없다. 이 일로 주변 소들이 분개하였다. 친구네 집에 놀러 갈 수 없을 뿐만 아니라, 매년 참가하던 국제 젖 짜기 올림피아드에도 올해는 참가할 수 없게 되었기 때문이다.

이웃 농장의 소 중 존의 농장에 방문할 수 있는 소가 조금 있긴 하지만, 그들도 안심할 수 있는 건 아니다. 존의 농장에 들어가는 문은 하나밖에 없고, 그 문을 통과하려면 감시관의 길고 긴 검문을 받아야 한다. 여러 마리의 소가 한 번에 들어가려고 하면 줄이 그 만큼 길어진다.

N마리의 소가 이 농장에 방문하러 왔다. 소가 도착한 시간과 검문받는 데 걸리는 시간은 소마다 다르다. (물론 같을 수도 있다.) 두 소가 동시에 검문을 받을 수는 없다. 예를 들어, 한 소가 5초에 도착했고 7초 동안 검문을 받으면, 8초에 도착한 그 다음 소는 12초까지 줄을 서야 검문을 받을 수 있다.

모든 소가 농장에 입장하려면 얼마나 걸리는 지 구해보자.

입력

첫 줄에 100 이하의 양의 정수 N이 주어진다. 다음 N줄에는 한 줄에 하나씩 소의 도착 시각과 검문 시간이 주어진다. 각각 1,000,000 이하의 양의 정수이다.

출력

모든 소가 농장에 입장하는 데 걸리는 최소 시간을 출력한다.

예제 입력 1 복사

3
2 1
8 3
5 7

예제 출력 1 복사

15

 

문제풀이(1)

1 2(1번소) 3(1번소 검사완료) 4 5(3번소) 6 7 8 9 10 11 12(3번소 검사완료) 13(2번소) 14 15(2번소 검사완료)
위와 같이 진행될 때 소는 먼저온 순서로 들어가는 형식이다. 그렇기때문에 소의 도착시간 순서로 정렬한 뒤 계산한다.
배열 순회할 때 마다 time에 start + end를 더해준다.
이때, 현재 time > start이면 time에 end 만 더해주고, time <= start 일 경우 start - time + end로 계산한다.
start - time을 하는 이유는 이전에 지나간 시간은 start에서 제거를 해야하기 때문이다.

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

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

let time = 0;

arr.forEach((value) => {
  const [start, end] = value;
  if (time > start) {
    time += end;
  } else {
    time += start - time + end;
  }
});

console.log(time);

+ Recent posts