my study.

Coding Test/Baekjoon

[백준] 2251 물통, java

fftl 2023. 4. 18. 00:28
 

2251번: 물통

각각 부피가 A, B, C(1≤A, B, C≤200) 리터인 세 개의 물통이 있다. 처음에는 앞의 두 물통은 비어 있고, 세 번째 물통은 가득(C 리터) 차 있다. 이제 어떤 물통에 들어있는 물을 다른 물통으로 쏟아 부

www.acmicpc.net

문제 간단 설명

 

A, B, C 각각 세 개의 물통이 주어집니다. 그리고 최초에 C 물통에는 물이 가득 차있으며 이 물통의 물을 각각 다른 물통으로 옮길 수 있습니다. 다만 물을 옮길 때, 받는 대상이 가득 차던지, 주는 대상이 비워지든지 해야합니다. 이렇게 계속해서 물을 옮길 때, A 물통이 비어있을 때, C 물통에 담겨있을 수 있는 물의 양을 모두 구하는 문제입니다.

 


문제 풀이

 

저는 아무래도 물통이 세 개 뿐이다 보니, 모든 경우의 수를 확인하는 것이 충분하다고 생각했습니다. 그래서 한 번씩 물을 이동시키며 방문(?) 했던 물의 크기들은 저장해두면서 모든 경우의 수를 확인했습니다. 다만 여기서 A, B, C 물통의 상태를 방문 처리하는 것에 조금 고생을 했지만 삼차원 배열을 이용하여 방문 표시를 하여 해결했습니다.


코드

package com.baekjoon.gold;

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.LinkedList;
import java.util.Queue;
import java.util.StringTokenizer;
import java.util.TreeSet;

public class Main_BJ_02251_G5_물통 {
	static int as, bs, cs;
	static int[] frame;
	static boolean[][][] visited;
	
	public static void main(String[] args) throws Exception{
		//데이터 입력!
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		StringTokenizer st = new StringTokenizer(br.readLine());
		TreeSet<Integer> res = new TreeSet<>(); //결과를 오름차순으로 출력해야 하기에 TreeSet을 이용하였습니다.
		int a = Integer.parseInt(st.nextToken());
		int b = Integer.parseInt(st.nextToken());
		int c = Integer.parseInt(st.nextToken());
		
		//일단 시작할 때 a가 0이기에 c의 값을 미리 저장합니다.
		res.add(c);
		
		as = 0; bs = 0; cs = c; //실제 물통에 담겨있는 물을 저장합니다.
		frame = new int[] {a, b, c}; //물통의 크기를 저장합니다.
		
		visited = new boolean[201][201][201]; //최대 현재 A, B, C의 크기에 방문한 적이 있는지 표시합니다.
		Queue<int[]> q = new LinkedList<>(); //bfs를 하기위한 Queue 입니다.
		
		//최초의 상태를 q에 넣어주고, 방문처리 해줍니다.
		q.add(new int[] {as,bs,cs});
		visited[as][bs][cs] = true;
		
		//bfs 시작!
		while(!q.isEmpty()) {
			int[] now = q.poll();
			
			//현재 A,B,C 상태에서 이동할 수 있는 모든 경우의수는 6개
			//각각을 모두 확인하며 A==0 의 상태를 확인하며 res를 추가하고
			//방문여부를 확인하여 방문하지 않았다면 Queue를 추가해줍니다.
			for(int i=0; i<3; i++) {
				for(int j=0; j<3; j++) {
					if(i==j) continue;
					int[] nowC = move(i, j, now);
					if(now[0] == 0) res.add(now[2]);
					if(!visited[nowC[0]][nowC[1]][nowC[2]]) {
						visited[nowC[0]][nowC[1]][nowC[2]] = true;
						q.add(nowC);
					} else {
					}
				}
			}
		}
		
		
		//bfs 탐색을 끝내고 res에 담긴 값들을 꺼내서 출력하여 줍니다!
		StringBuilder sb = new StringBuilder();
		while(!res.isEmpty()) {
			sb.append(res.pollFirst()+" ");
		}
		
		//답!!
		System.out.println(sb.toString().trim());
	}
	
	//문제 풀이의 핵심이 되는 move 함수입니다. from에서 to로 물을 옮겨주는 행위를 하는 메소드입니다.
	static int[] move(int from, int to, int[] now) {
		
		int yubun = frame[to]-now[to]; //물을 받을 물통에 물을 받을수 있는 공간이 얼마나 남았는지 확인해줍니다.
		int motgan = (now[from]-yubun) > 0 ? now[from]-yubun : 0; //만약 받을 수 있는 공간이 더 크다면 물을 모두 넘겨주고 못간 값을 0으로 아니라면 못간 물을 남깁니다.
		int gan = now[from] - motgan; //물이 얼마나 넘어갔는지 구해줍니다.
		
		int[] result = new int[3];
		boolean[] visit = new boolean[3];
		visit[from] = true;
		visit[to] = true;
		
		//못간 값과
		//이동한 후의 값들을 각각 담아줍니다.
		result[from] = motgan;
		result[to] = now[to]+gan;
		
		for(int i=0; i<3; i++) {
			if(!visit[i]) result[i] = now[i];
		}
		
		//반환합니다!
		return result;
	}
}

'Coding Test > Baekjoon' 카테고리의 다른 글

[백준] 15591 MooTube, java  (0) 2023.09.03
[백준] 1806 부분합, java  (0) 2023.05.09
[백준] 15684 사다리 조작, java  (0) 2023.04.15
[백준] 15683 감시, java  (0) 2023.04.11
[백준] 21608 상어 초등학교, java  (0) 2023.04.08