백준 2251 물통

2025. 1. 1. 17:01·코딩테스트/bfs (Breadth-first search)

링크 : https://www.acmicpc.net/problem/2251

문제 설명

더보기

문제

각각 부피가 A, B, C(1≤A, B, C≤200) 리터인 세 개의 물통이 있다. 처음에는 앞의 두 물통은 비어 있고, 세 번째 물통은 가득(C 리터) 차 있다. 이제 어떤 물통에 들어있는 물을 다른 물통으로 쏟아 부을 수 있는데, 이때에는 한 물통이 비거나, 다른 한 물통이 가득 찰 때까지 물을 부을 수 있다. 이 과정에서 손실되는 물은 없다고 가정한다.

이와 같은 과정을 거치다보면 세 번째 물통(용량이 C인)에 담겨있는 물의 양이 변할 수도 있다. 첫 번째 물통(용량이 A인)이 비어 있을 때, 세 번째 물통(용량이 C인)에 담겨있을 수 있는 물의 양을 모두 구해내는 프로그램을 작성하시오.

입력

첫째 줄에 세 정수 A, B, C가 주어진다.

출력

첫째 줄에 공백으로 구분하여 답을 출력한다. 각 용량은 오름차순으로 정렬한다.


문제 풀이

a → b, c

b → a, c

c → a, b 로 물을 옮기는 경우의 수를 전부 구하고 (단, 중복이 되는 경로는 추가가 되면 안됨)

a가 0이 되었을 경우 c의 값을 answer에 추가 최종적으로 answer을 중복제거하고 정렬하여 ‘ ‘로 이어주면 됨.

const inputs = require("fs")
  .readFileSync("/dev/stdin")
  .toString()
  .trim()
  .split("\n");

let [a, b, c] = inputs[0].split(" ").map(Number);

// bfs
let answer = [];
let visited = new Set();
let check = [[0, 0, c]];

const processVisited = (tmp) => {
  const key = JSON.stringify(tmp);
  if (!visited.has(key)) {
    check.push(tmp);
    visited.add(key);
  }
};

const transfer = (state, from, to, limit) => {
  const nextState = [...state];
  const transfer_amount = Math.min(limit - nextState[to], nextState[from]);

  nextState[from] -= transfer_amount;
  nextState[to] += transfer_amount;

  processVisited(nextState);
};

const bfs = () => {
  while (check.length > 0) {
    let current = check.pop();
    // 물통이 비어있으면 C 추가
    if (current[0] === 0) {
      answer.push(current[2]);
    }

    // 물을 옮길 수 있는 경우 구하기
    // a -> b
    transfer(current, 0, 1, b);
    // a -> c
    transfer(current, 0, 2, c);
    // b -> a
    transfer(current, 1, 0, a);
    // b -> c
    transfer(current, 1, 2, c);
    // c -> a
    transfer(current, 2, 0, a);
    // c -> b
    transfer(current, 2, 1, b);
  }
};

bfs();

console.log([...new Set(answer)].sort((a, b) => a - b).join(" "));

결론

물을 옮기는 경우의 수에 대한 로직을 if로 전부 처리하였는데 해당 로직을 transfer함수로 분리하였음

→ 코드 중복 제거 및 가독성 증가

 

[1, 2, 3] 형태를 set에 추가하여 has()를 통해 검사를 하려고 하였는데 동일한 참조(reference)가 아니면 제대로 검사가 안됨

→ 해당 부분은 JSON.stringify를 이용해 문자열로 변환하여 검사하도록 함

 

그 외 js 문법 정리 (Set, dict)

더보기

1. let a = {}의 경우

let a = {};
b = [1, 2, 3];
a.add(b); // TypeError: a.add is not a function
  • a는 일반 객체(Object)입니다.
  • 객체에는 add 메서드가 기본적으로 존재하지 않습니다.
  • 일반 객체에서는 키-값 쌍을 정의하거나 속성을 추가하는 방식으로만 사용할 수 있습니다.

일반 객체에서 동작 예:

let a = {};
a["key"] = [1, 2, 3]; // 객체에 속성 추가
console.log(a); // { key: [1, 2, 3] }

2. let a = new Set()의 경우

let a = new Set();
b = [1, 2, 3];
a.add(b); // 정상 작동
console.log(a); // Set { [1, 2, 3] }
  • Set은 고유한 값들을 저장하는 특수한 데이터 구조입니다.
  • Set에는 add 메서드가 정의되어 있어, 값을 추가할 수 있습니다.
  • 이 경우, 참조 타입(b라는 배열)은 객체의 참조를 저장합니다.

핵심 차이

특징 일반 객체 {} Set
메서드 지원 add 없음 add, has, delete 지원
저장 방식 키-값 쌍(a[key] = value) 값만 저장 (고유한 값 유지)
참조 비교 직접 관리 필요 (JSON.stringify 등) 참조 기준으로 동작

 

'코딩테스트 > bfs (Breadth-first search)' 카테고리의 다른 글

백준 13265 색칠하기  (1) 2025.02.17
백준 14502 연구소  (0) 2025.02.13
백준 4179 불!  (3) 2025.01.17
'코딩테스트/bfs (Breadth-first search)' 카테고리의 다른 글
  • 백준 13265 색칠하기
  • 백준 14502 연구소
  • 백준 4179 불!
의현
의현
개발은 즐거워
  • 의현
    UIHYEON BLOG
    의현
  • 전체
    오늘
    어제
    • 분류 전체보기 (118)
      • 프론트엔드 (47)
        • JavaScript (47)
        • TypeScript (0)
        • HTML (0)
        • CSS (0)
        • React (0)
      • 프로젝트 (2)
        • Task Flow (2)
      • 코딩테스트 (68)
        • Binary Search (2)
        • bfs (Breadth-first s.. (4)
        • dfs (Deapth-first se.. (1)
        • Greedy (1)
        • Dynamic Programming (1)
        • two pointer (4)
        • 구현 (2)
        • LIS(Longest Increasi.. (0)
        • 문자열 (3)
        • 자료구조 (4)
        • 비트마스크 (2)
        • 수학 (2)
        • 프로그래머스 (42)
  • 인기 글

  • 최근 글

  • 최근 댓글

  • hELLO· Designed By정상우.v4.10.3
의현
백준 2251 물통
상단으로

티스토리툴바