각각 부피가 A, B, C(1 ≤ A, B, C ≤ 200) 리터인 3개의 물통이 있다. 처음에는 앞의 두 물통은 비어 있고, 3번째 물통(C 리터)은 가득 차 있다. 이제 어떤 물통에 들어 있는 물을 다른 물통으로 쏟아부을 수 있는데, 이때는 한 물통이 비거나, 다른 한 물통이 가득 찰 때까지 물을 부을 수 있다. 이 과정에서 손실되는 물은 없다고 가정한다. 이와 같은 과정을 거치다 보면 3번째 물통(용량이 C인)에 담겨 있는 물의 양이 변할 수도 있다. 1반째 물통(용량이 A인)이 비어 있을 때 3번째 물통(용량이 C인)에 담겨 있을 수 있는 물의 양을 모두 구하는 프로그램을 작성하시오.
(시간 제한 1초)
1번째 줄에 세 정수 A, B, C가 주어진다.
1번째 줄에 공백으로 구분해 답을 출력한다. 각 용량은 오름차순 정렬한다.
예제 입력
8 9 10 // A B C
예제 출력
1 2 8 9 10
1단계
- 문제 분석하기그래프로 데이터를 저장하고 작성하는 자료구조를 이용하는 방식과 달리, 그래프의 원리를 적용해 그래프를 역으로 그리는 방식으로 접근하는 문제이다.
A, B, C의 특정 무게 상태를 1개의 노드로 가정하고, 조건에 따라 이 상태에서 변경할 수 있는 이후 무게 상태가 에지로 이어진 인접 노드라고 생각하고 문제에 접근해 보자.
2단계
- 손으로 풀어 보기1
처음에 물통 A, B는 비어 있고, C는 꽉 차 있으므로 최초 출발 노드를 (0, 0, 3번째 물통의 용량)으로 초기화한다.
2
BFS를 수행한다. 탐색 과정은 다음과 같다.
3
정답 리스트를 오름차순 출력
3단계
- sudo코드 작성하기Sender, Receiver (6가지 경우를 탐색하기 위한 선언 배열)
visited(방문 배열 저장)
answer(정답 배열)
now(A, B, C 값을 저장하는 배열)
now 배열 저장하기
visited, answer 초기화
BFS 수행
for(answer 배열 탐색)
answer 배열에서 값이 true인 index 정답으로 출력
BFS {
큐 자료구조에 출발 노드 추가(0, 0, C 노드에서 시작)
visited 배열에 현재 노드 추가
answer 배열에 현재 C값 체크 (A가 0으로 시작하기 때문에)
while(큐가 빌 때 까지)
{
큐에서 노드 가져오기(poll)
데이터를 이용해 A, B, C값 초기화
for(6가지 케이스 반복)
{
받는 물통에 보내려는 물통의 값 더하기
보내려는 물통 값을 0으로 업데이트
if(받는 물통이 넘칠 때)
{
넘치는 만큼 보내는 물통에 다시 넣기.
받는 물통을 물통의 최댓값으로 저장
}
현재 노드의 연결 노드 중 방문하지 않은 노드로 이동
큐에 데이터 삽입(add)하고 visited 배열에 방문 기록
if(1번째 물통이 비어 있을 때)
3번째 물통의 물의 양을 answer 배열에 기록
}
}
}
// A, B 클래스 선언(A, B값만 지니고 있으면 C값은 유추할 수 있으므로 A, B만 저장)
class AB {
A, B 물통 무게를 변수로 지님.
}
4단계
- 코드 구현하기import java.util.LinkedList;
import java.util.Queue;
import java.util.Scanner;
public class Q49 {
// 6가지 이동 케이스를 표현하기 위한 배열
static int[] Sender = {0, 0, 1, 1, 2, 2};
static int[] Receiver = {1, 2, 0 ,2, 0, 1};
static boolean visited[][]; // A, B의 무게를 체크
static boolean answer[];
static int now[];
public static void main(String[] args){
Scanner sc = new Scanner(System.in);
now = new int[3];
now[0] = sc.nextInt();
now[1] = sc.nextInt();
now[2] = sc.nextInt();
visited = new boolean[201][201];
answer = new boolean[201];
BFS();
for(int i = 0; i < answer.length; i++){
if(answer[i])
System.out.print(i + " ");
}
}
public static void BFS(){
Queue<AB>queue = new LinkedList<>();
queue.add(new AB(0, 0));
visited[0][0] = true;
answer[now[2]] = true;
while (!queue.isEmpty()){
AB p = queue.poll();
int A = p.A;
int B = p.B;
int C = now[2] - A - B;
for(int k = 0; k < 6; k++){
int[] next = {A, B, C};
next[Receiver[k]] += next[Sender[k]];
next[Sender[k]] = 0;
if(next[Receiver[k]] > now[Receiver[k]]){
next[Sender[k]] = next[Receiver[k]] - now[Receiver[k]];
next[Receiver[k]] = now[Receiver[k]];
}
if(!visited[next[0]][next[1]]){
visited[next[0]][next[1]] = true;
queue.add(new AB(next[0], next[1]));
if(next[0] == 0)
answer[next[2]] = true;
}
}
}
}
}
class AB{
int A;
int B;
public AB(int A, int B){
this.A = A;
this.B = B;
}
}
- Do it! 알고리즘 코딩테스트 자바 편