백준 물통 - 2551 [JAVA] - 23년 1월 23일

Denia·2023년 1월 23일
0

코딩테스트 준비

목록 보기
143/201

리팩토링 전

package CodingTest.Baekjoon;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.*;

public class Main {
    static public void main(String[] args) throws IOException {
        BjSolution sol = new BjSolution();

        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        String[] input = br.readLine().split(" ");

        sol.solution(input);
    }
}

class BjSolution {
    Set<WATER> set;
    int TotalA, TotalB, TotalC;

    public void solution(String[] input) {
        set = new TreeSet<>();

        TotalA = Integer.parseInt(input[0]);
        TotalB = Integer.parseInt(input[1]);
        TotalC = Integer.parseInt(input[2]);

        bfs(0, 0, TotalC);

        for (WATER water : set) {
            System.out.print(water.C + " ");
        }
    }

    private void bfs(int A, int B, int C) {
        Deque<WATER> dq = new ArrayDeque<>();
        Map<String, Integer> visited = new HashMap<>();

        WATER startWater = new WATER(A, B, C);
        dq.offerLast(startWater);
        isIncluded(visited, startWater);
        while (!dq.isEmpty()) {
            WATER curWater = dq.pollFirst();
            if (curWater.A == 0) {
                set.add(curWater);
            }

            //A->B
            int moveWater = Math.min(curWater.A, TotalB - curWater.B);
            if (moveWater != 0) {
                WATER newWater = new WATER(curWater.A - moveWater, curWater.B + moveWater, curWater.C);
                if (!isIncluded(visited, newWater)) {
                    dq.offerLast(newWater);
                }
            }
            //A->C
            moveWater = Math.min(curWater.A, TotalC - curWater.C);
            if (moveWater != 0) {
                WATER newWater = new WATER(curWater.A - moveWater, curWater.B, curWater.C + moveWater);
                if (!isIncluded(visited, newWater)) {
                    dq.offerLast(newWater);
                }
            }
            //B->A
            moveWater = Math.min(curWater.B, TotalA - curWater.A);
            if (moveWater != 0) {
                WATER newWater = new WATER(curWater.A + moveWater, curWater.B - moveWater, curWater.C);
                if (!isIncluded(visited, newWater)) {
                    dq.offerLast(newWater);
                }
            }
            //B->C
            moveWater = Math.min(curWater.B, TotalC - curWater.C);
            if (moveWater != 0) {
                WATER newWater = new WATER(curWater.A, curWater.B - moveWater, curWater.C + moveWater);
                if (!isIncluded(visited, newWater)) {
                    dq.offerLast(newWater);
                }
            }
            //C->A
            moveWater = Math.min(curWater.C, TotalA - curWater.A);
            if (moveWater != 0) {
                WATER newWater = new WATER(curWater.A + moveWater, curWater.B, curWater.C - moveWater);
                if (!isIncluded(visited, newWater)) {
                    dq.offerLast(newWater);
                }
            }
            //C->B
            moveWater = Math.min(curWater.C, TotalB - curWater.B);
            if (moveWater != 0) {
                WATER newWater = new WATER(curWater.A, curWater.B + moveWater, curWater.C - moveWater);
                if (!isIncluded(visited, newWater)) {
                    dq.offerLast(newWater);
                }
            }
        }
    }

    private boolean isIncluded(Map<String, Integer> visit, WATER water) {
        if (visit.containsKey(water.toString())) return true;

        visit.put(water.toString(), 1);
        return false;
    }
}

class WATER implements Comparable<WATER> {
    int A;
    int B;
    int C;

    public WATER(int A, int B, int C) {
        this.A = A;
        this.B = B;
        this.C = C;
    }

    public String toString() {
        return A + " " + B + " " + C;
    }

    @Override
    public int compareTo(WATER o) {
        return Integer.compare(this.C, o.C);
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        WATER water = (WATER) o;
        return A == water.A && B == water.B && C == water.C;
    }

    @Override
    public int hashCode() {
        return Objects.hash(A, B, C);
    }
}

리팩토링 후

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.Set;
import java.util.TreeSet;

public class Main {
    static public void main(String[] args) throws IOException {
        BjSolution sol = new BjSolution();

        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        String[] input = br.readLine().split(" ");

        sol.solution(input);
    }
}

class BjSolution {
    final int WATER_MAX_SIZE = 200;
    int TotalA, TotalB, TotalC;
    Set<Integer> set;
    boolean[][][] visited;
    int[] waterMaxArr;

    public void solution(String[] input) {
        set = new TreeSet<>();
        visited = new boolean[WATER_MAX_SIZE + 1][WATER_MAX_SIZE + 1][WATER_MAX_SIZE + 1];

        TotalA = Integer.parseInt(input[0]);
        TotalB = Integer.parseInt(input[1]);
        TotalC = Integer.parseInt(input[2]);
        waterMaxArr = new int[]{TotalA, TotalB, TotalC};

        bfs(0, 0, TotalC);

        for (int val : set) {
            System.out.print(val + " ");
        }
    }

    private void bfs(int A, int B, int C) {
        Deque<WATER> dq = new ArrayDeque<>();

        WATER startWater = new WATER(A, B, C);

        visited[startWater.A][startWater.B][startWater.C] = true;
        dq.offerLast(startWater);

        while (!dq.isEmpty()) {
            WATER curWater = dq.pollFirst();

            if (curWater.A == 0) {
                set.add(curWater.C);
            }

            for (int from = 0; from < 3; from++) {
                for (int to = 0; to < 3; to++) {
                    if (from == to) continue;

                    moveWater(dq, curWater, from, to);
                }
            }
        }
    }

    private void moveWater(Deque<WATER> dq, WATER curWater, int from, int to) {
        int[] waterArr = {curWater.A, curWater.B, curWater.C};
        int moveWater = Math.min(waterArr[from], waterMaxArr[to] - waterArr[to]);

        if (moveWater == 0) return;
        
        waterArr[from] -= moveWater;
        waterArr[to] += moveWater;

        WATER newWater = new WATER(waterArr[0], waterArr[1], waterArr[2]);

        if (visited[newWater.A][newWater.B][newWater.C]) return;

        visited[newWater.A][newWater.B][newWater.C] = true;
        dq.offerLast(newWater);
    }
}

class WATER {
    int A, B, C;

    public WATER(int A, int B, int C) {
        this.A = A;
        this.B = B;
        this.C = C;
    }
}

profile
HW -> FW -> Web

0개의 댓글