본문 바로가기
알고리즘/백준

[백준 2251] 물통

by RoJae 2019. 4. 25.


 물통의 갯수는 세개이고 물통의 크기는 1부터 200까지이다.


 이때 물통의 갯수가 세개이기 때문에

 모든 경우를 고려한 BFS 알고리즘을 사용하여

 A 물통이 비어있을 때, C의 물통에 담겨 있는 물의 양을 출력하면 된다.


 모든 경우라고 해봤자.  총 6가지이다

1. A -> B

2. A -> C

3. B -> A

4. B -> C

5. C -> A

6. C -> B

( 각각의 모든 경우는, 옮기려는 물들이 옮기려는 곳의 최대 용량보다 많은지 검사를 해야한다.)

음수가 나오므로 불 필요한 연산을 하지 않기 위해서


 1. 임의로 만든 water 구조를 사용하여, 저장 및 사용이 편리하도록 Queue<water>을 사용하였다.

 2. 방문 여부를 확인 하기 위해서 bool visit[][][]를 작성하였다.





출처 : https://www.acmicpc.net/problem/2251

문제

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

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

입력

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

출력

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

예제 입력 1

8 9 10

예제 출력 1

1 2 8 9 10




소스코드

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
#include<iostream>
#include<queue>
#include<set>
 
using namespace std;
 
bool visit[201][201][201];        // 방문 여부 확인 
 
struct water {
    int A, B, C;                    // 현재 담긴 물
};
 
int main(void) {
    int A, B, C;                // 물통의 용량 크기 
    cin >> A >> B >> C;            // 물통의 용량
    set<int> ans;                // 정답을 담을 컨테이너 
    queue<water> q;                // water 구조를 사용한 queue 컨테이너 
    q.push({ 0,0,C });            // queue에 초기 값을 삽입한다. 
 
    while (!q.empty()) {
        int curr_A = q.front().A;        // 현재 A에 담겨 있는 물의 양 
        int curr_B = q.front().B;        // 현재 B에 담겨 있는 물의 양 
        int curr_C = q.front().C;        // 현재 C에 담겨 있는 물의 양 
        q.pop();
        
        if (visit[curr_A][curr_B][curr_C])        // 이미 방문한 경우 
            continue;
        
        // 첫 방문 
        visit[curr_A][curr_B][curr_C] = true;
 
        // A의 물이 0일때 
        if (curr_A == 0) {
            ans.insert(curr_C);
        }
        // case 1    a -> b
        if (curr_A + curr_B > B)
            q.push({ curr_A + curr_B - B, B, curr_C });
        else
            q.push({ 0, curr_A + curr_B, curr_C });
 
        // case 2     a -> c
        if (curr_A + curr_C > C)
            q.push({ curr_A + curr_C - C, curr_B, C });
        else
            q.push({ 0, curr_B, curr_A + curr_C });
            
        // case 3    b -> a
        if (curr_A + curr_B > A)
            q.push({ A, curr_A + curr_B - A, curr_C });
        else
            q.push({ curr_A + curr_B, 0, curr_C });
 
        // case 4    b -> c
        if (curr_B + curr_C > C)
            q.push({ curr_A, curr_B + curr_C - C , C });
        else
            q.push({ curr_A, 0, curr_B + curr_C });
            
        // case 5    c -> b
        if (curr_B + curr_C > B)
            q.push({ curr_A, B, curr_B + curr_C - B });    
        else
            q.push({ curr_A, curr_B + curr_C, 0 });     
 
        // case 6    c -> a
        if (curr_A + curr_C > A)
            q.push({ A, curr_B, curr_A + curr_C - A });
        else
            q.push({ curr_A + curr_C, curr_B, 0 });
 
    }
 
    // 정답 출력 
    set<int>::iterator iter;
    for (iter = ans.begin(); iter != ans.end(); iter++)
        cout << *iter << ' ';
        
    // 종료 
    return 0;
}

cs



※ 본 글은 개인 포트폴리오 혹은 공부용으로 사용하기 때문에, 무단 복사 유포는 금지하지만, 개인 공부 용도로는 얼마든지 사용하셔도 좋습니다.



'알고리즘 > 백준' 카테고리의 다른 글

[백준 1759] 암호 만들기  (0) 2019.04.28
[백준 9095] 1,2,3 더하기  (0) 2019.04.28
[백준 9019] DSLR  (0) 2019.04.24
[백준1963] 소수 경로  (0) 2019.04.23

댓글