문제

문제 설명

네트워크란 컴퓨터 상호 간에 정보를 교환할 수 있도록 연결된 형태를 의미합니다. 예를 들어, 컴퓨터 A와 컴퓨터 B가 직접적으로 연결되어있고, 컴퓨터 B와 컴퓨터 C가 직접적으로 연결되어 있을 때 컴퓨터 A와 컴퓨터 C도 간접적으로 연결되어 정보를 교환할 수 있습니다. 따라서 컴퓨터 A, B, C는 모두 같은 네트워크 상에 있다고 할 수 있습니다.

컴퓨터의 개수 n, 연결에 대한 정보가 담긴 2차원 배열 computers가 매개변수로 주어질 때, 네트워크의 개수를 return 하도록 solution 함수를 작성하시오.

제한사항

  • 컴퓨터의 개수 n은 1 이상 200 이하인 자연수입니다.
  • 각 컴퓨터는 0부터 n-1인 정수로 표현합니다.
  • i번 컴퓨터와 j번 컴퓨터가 연결되어 있으면 computers[i][j]를 1로 표현합니다.
  • computer[i][i]는 항상 1입니다.

입출력 예

n computers return

3 [[1, 1, 0], [1, 1, 0], [0, 0, 1]] 2
3 [[1, 1, 0], [1, 1, 1], [0, 1, 1]] 1

입출력 예 설명

예제 #1

아래와 같이 2개의 네트워크가 있습니다.

예제 #2

아래와 같이 1개의 네트워크가 있습니다.

풀이

DFS 또는 BFS로 풀 수 있는 문제로, 나는 BFS를 사용해서 풀었다. 각 노드들을 순회하면서, 만약 방문하지 않은 노드라면 큐에 넣은 후 연결된 노드를 모두 탐색하여 방문처리 해준다. 방문처리가 끝났다면 answer 값을 증가 시켜주면 된다.

코드

import java.util.LinkedList;
import java.util.Queue;

class Solution {
    public int solution(int n, int[][] computers) {
        int answer = 0;
        boolean[] visited = new boolean[n];
        Queue<Integer> queue = new LinkedList<>();
        for (int i = 0; i < n; i++) {
            if (!visited[i]) {
                visited[i] = true;
                queue.add(i);
                while (!queue.isEmpty()) {
                    int idx = queue.poll();
                    for (int j = 0; j < computers[idx].length; j++) {
                        if (!visited[j] && computers[idx][j] == 1) {
                            visited[j] = true;
                            queue.add(j);
                        }
                    }
                }
                answer++;
            }
        }

        return answer;
    }
}

문제

문제 설명

이중 우선순위 큐는 다음 연산을 할 수 있는 자료구조를 말합니다.

명령어 수신 탑(높이)

I 숫자 큐에 주어진 숫자를 삽입합니다.
D 1 큐에서 최댓값을 삭제합니다.
D -1 큐에서 최솟값을 삭제합니다.

이중 우선순위 큐가 할 연산 operations가 매개변수로 주어질 때, 모든 연산을 처리한 후 큐가 비어있으면 [0,0] 비어있지 않으면 [최댓값, 최솟값]을 return 하도록 solution 함수를 구현해주세요.

제한사항

  • operations는 길이가 1 이상 1,000,000 이하인 문자열 배열입니다.
  • operations의 원소는 큐가 수행할 연산을 나타냅니다.
    • 원소는 “명령어 데이터” 형식으로 주어집니다.- 최댓값/최솟값을 삭제하는 연산에서 최댓값/최솟값이 둘 이상인 경우, 하나만 삭제합니다.
  • 빈 큐에 데이터를 삭제하라는 연산이 주어질 경우, 해당 연산은 무시합니다.

입출력 예

operations return

["I 16", "I -5643", "D -1", "D 1", "D 1", "I 123", "D -1"] [0,0]
["I -45", "I 653", "D 1", "I -642", "I 45", "I 97", "D 1", "D -1", "I 333"] [333, -45]

입출력 예 설명

입출력 예 #1

  • 16과 -5643을 삽입합니다.
  • 최솟값을 삭제합니다. -5643이 삭제되고 16이 남아있습니다.
  • 최댓값을 삭제합니다. 16이 삭제되고 이중 우선순위 큐는 비어있습니다.
  • 우선순위 큐가 비어있으므로 최댓값 삭제 연산이 무시됩니다.
  • 123을 삽입합니다.
  • 최솟값을 삭제합니다. 123이 삭제되고 이중 우선순위 큐는 비어있습니다.

따라서 [0, 0]을 반환합니다.

입출력 예 #2

  • 45와 653을 삽입후 최댓값(653)을 삭제합니다. -45가 남아있습니다.
  • 642, 45, 97을 삽입 후 최댓값(97), 최솟값(-642)을 삭제합니다. -45와 45가 남아있습니다.
  • 333을 삽입합니다.

이중 우선순위 큐에 -45, 45, 333이 남아있으므로, [333, -45]를 반환합니다.

풀이

문제의 제목처럼, 우선순위 큐를 최댓값을 기준으로 꺼내는 큐, 최솟값을 기준으로 꺼내는 큐 두가지를 가지도록 한다. 이 후 I 연산이 나왔을 때 두 큐에 값을 추가해주고, D 연산이 나왔을 때에는 각 큐에서 값 제거 후 다른 큐에 남아있는 동일한 값을 제거해준다. 이후 answer 배열에 최댓값, 최솟값을 담아서 리턴해준다.

코드

import java.util.Comparator;
import java.util.PriorityQueue;

class Solution {
    public int[] solution(String[] operations) {
        int[] answer = new int[2];
        PriorityQueue<Integer> maxQueue = new PriorityQueue<Integer>(Comparator.reverseOrder());
        PriorityQueue<Integer> minQueue = new PriorityQueue<Integer>();
        for (int i = 0; i < operations.length; i++) {
            String[] splited = operations[i].split(" ");
            if (splited[0].equals("I")) {
                maxQueue.add(Integer.parseInt(splited[1]));
                minQueue.add(Integer.parseInt(splited[1]));
            } else {
                if (splited[1].equals("1") && !maxQueue.isEmpty()) {
                    minQueue.remove(maxQueue.poll());
                } else if (splited[1].equals("-1") && !minQueue.isEmpty()) {
                    maxQueue.remove(minQueue.poll());
                }

            }
        }
        if (!maxQueue.isEmpty())
            answer[0] = maxQueue.poll();
        if (!minQueue.isEmpty())
            answer[1] = minQueue.poll();

        return answer;
    }
}

문제

문제 설명

두 수의 최소공배수(Least Common Multiple)란 입력된 두 수의 배수 중 공통이 되는 가장 작은 숫자를 의미합니다. 예를 들어 2와 7의 최소공배수는 14가 됩니다. 정의를 확장해서, n개의 수의 최소공배수는 n 개의 수들의 배수 중 공통이 되는 가장 작은 숫자가 됩니다. n개의 숫자를 담은 배열 arr이 입력되었을 때 이 수들의 최소공배수를 반환하는 함수, solution을 완성해 주세요.

제한 사항

  • arr은 길이 1이상, 15이하인 배열입니다.
  • arr의 원소는 100 이하인 자연수입니다.

입출력 예

arr result

[2,6,8,14] 168
[1,2,3] 6

풀이

n개의 주어진 수들의 최소 공배수를 구하는 문제이다.

a와 b의 최소공배수는 a와 b의 곱을 a와 b의 최대공약수를 나눈 것과 같다. 라는 특성을 활용하면 된다.

따라서, 먼저 유클리드 호제법을 활용하여 최대공약수를 계산하고, 그 결과를 활용하여 최소공배수를 업데이트 시켜주면 된다.

코드

class Solution {
 public static int gcd(int a, int b) {
        int x = Math.max(a,b);
        int y = Math.min(a,b);

        while (x % y != 0) {
            int r = x % y;
            x = y;
            y = r;
        }
        return y;
    }
    public int solution(int[] arr) {
        int answer = arr[0];

        for (int i = 1; i < arr.length; i++) {
            int gcd = gcd(answer, arr[i]);

            answer = answer * arr[i] / gcd;
        }
        return answer;
    }
}

문제

문제 설명

정수로 이루어진 배열 numbers가 있습니다. 배열 의 각 원소들에 대해 자신보다 뒤에 있는 숫자 중에서 자신보다 크면서 가장 가까이 있는 수를 뒷 큰수라고 합니다.

정수 배열 numbers가 매개변수로 주어질 때, 모든 원소에 대한 뒷 큰수들을 차례로 담은 배열을 return 하도록 solution 함수를 완성해주세요. 단, 뒷 큰수가 존재하지 않는 원소는 -1을 담습니다.


제한사항

  • 4 ≤ numbers의 길이 ≤ 1,000,000
    • 1 ≤ numbers[i] ≤ 1,000,000

입출력 예

numbers result

[2, 3, 3, 5] [3, 5, 5, -1]
[9, 1, 5, 3, 6, 2] [-1, 5, 6, 6, -1, -1]

입출력 예 설명

입출력 예 #1

2의 뒷 큰수는 3입니다. 첫 번째 3의 뒷 큰수는 5입니다. 두 번째 3 또한 마찬가지입니다. 5는 뒷 큰수가 없으므로 -1입니다. 위 수들을 차례대로 배열에 담으면 [3, 5, 5, -1]이 됩니다.

입출력 예 #2

9는 뒷 큰수가 없으므로 -1입니다. 1의 뒷 큰수는 5이며, 5와 3의 뒷 큰수는 6입니다. 6과 2는 뒷 큰수가 없으므로 -1입니다. 위 수들을 차례대로 배열에 담으면 [-1, 5, 6, 6, -1, -1]이 됩니다.

풀이

numbers의 길이가 1,000,000 이므로, 완전탐색으로는 풀 수 없는 문제이다.

Stack을 통해 뒤의 인덱스 부터 접근하여 비교할 경우 시간을 줄일 수 있을것이라고 생각하고 구현했다.

코드

import java.util.Stack;

class Solution {
    public int[] solution(int[] numbers) {
        // stack + 뒤에서 접근 한다면 풀릴거같다.
        Stack<Integer> stack = new Stack<>();
        Stack<Integer> result = new Stack<>();

        // 가장 마지막 원소는 항상 -1이다.
        stack.add(numbers[numbers.length-1]);
        result.add(-1);
        for (int i = numbers.length - 2 ; i >= 0; i--) {
            while(!stack.isEmpty()) {
                if (stack.peek() > numbers[i]) {
                    result.add(stack.peek());
                    break;
                } else {
                    stack.pop();
                }
            }
            if (stack.isEmpty())
                result.add(-1);

            stack.add(numbers[i]);
        }
        
        int[] answer = new int[numbers.length];
        for (int i = 0; i < numbers.length; i++) {
            answer[i] = result.pop();
        }
        return answer;
    }
}

문제

문제 설명

비내림차순으로 정렬된 수열이 주어질 때, 다음 조건을 만족하는 부분 수열을 찾으려고 합니다.

  • 기존 수열에서 임의의 두 인덱스의 원소와 그 사이의 원소를 모두 포함하는 부분 수열이어야 합니다.
  • 부분 수열의 합은 k입니다.
  • 합이 k인 부분 수열이 여러 개인 경우 길이가 짧은 수열을 찾습니다.
  • 길이가 짧은 수열이 여러 개인 경우 앞쪽(시작 인덱스가 작은)에 나오는 수열을 찾습니다.

수열을 나타내는 정수 배열 sequence와 부분 수열의 합을 나타내는 정수 k가 매개변수로 주어질 때, 위 조건을 만족하는 부분 수열의 시작 인덱스와 마지막 인덱스를 배열에 담아 return 하는 solution 함수를 완성해주세요. 이때 수열의 인덱스는 0부터 시작합니다.


제한사항

  • 5 ≤ sequence의 길이 ≤ 1,000,000
    • 1 ≤ sequence의 원소 ≤ 1,000
    • sequence는 비내림차순으로 정렬되어 있습니다.
  • 5 ≤ k ≤ 1,000,000,000
    • k는 항상 sequence의 부분 수열로 만들 수 있는 값입니다.

입출력 예

sequence k result

[1, 2, 3, 4, 5] 7 [2, 3]
[1, 1, 1, 2, 3, 4, 5] 5 [6, 6]
[2, 2, 2, 2, 2] 6 [0, 2]

입출력 예 설명

입출력 예 #1

[1, 2, 3, 4, 5]에서 합이 7인 연속된 부분 수열은 [3, 4]뿐이므로 해당 수열의 시작 인덱스인 2와 마지막 인덱스 3을 배열에 담아 [2, 3]을 반환합니다.

입출력 예 #2

[1, 1, 1, 2, 3, 4, 5]에서 합이 5인 연속된 부분 수열은 [1, 1, 1, 2], [2, 3], [5]가 있습니다. 이 중 [5]의 길이가 제일 짧으므로 해당 수열의 시작 인덱스와 마지막 인덱스를 담은 [6, 6]을 반환합니다.

입출력 예 #3

[2, 2, 2, 2, 2]에서 합이 6인 연속된 부분 수열은 [2, 2, 2]로 3가지 경우가 있는데, 길이가 짧은 수열이 여러 개인 경우 앞쪽에 나온 수열을 찾으므로 [0, 2]를 반환합니다.

풀이

기존 풀이

예전에 시도했던 문제여서 코드가 있었다. 이 코드의 경우 이중 for 문을 이용하게 되는데, sequence의 길이가 1,000,000 이하 이므로, 최악의 경우 100만 X 100만번의 연산을 수행하므로 결과 확인 시 시간초과가 발생하는것을 확인했다. 따라서, 연산횟수를 줄이는 방법을 고민해봐야 했다.

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;

class Solution {
    public int[] solution(int[] sequence, int k) {
        int[] answer;

        ArrayList<int []> arrayList = new ArrayList<int[]>();

        for (int i = 0; i < sequence.length; i++) {
            int sum = 0;
            int start = i;
            int end;
            for (int j = i; j < sequence.length; j++) {
                sum+= sequence[j];
                if (sum == k) {
                    end = j;
                    arrayList.add(new int[] {start, end});
                }else if (sum > k)
                    break;
            }

        }
        arrayList.sort(new Comparator<int[]>() {
            @Override
            public int compare(int[] o1, int[] o2) {
                return (o1[1] - o1[0]) - (o2[1] - o2[0]);
            }
        });

        //System.out.println(arrayList);
        answer = arrayList.get(0);

        return answer;
    }
}

코드 실행 결과

테스트 1 〉	통과 (2.62ms, 77.1MB)
테스트 2 〉	통과 (2.21ms, 79.4MB)
테스트 3 〉	통과 (2.51ms, 78.2MB)
테스트 4 〉	통과 (12.93ms, 78.4MB)
테스트 5 〉	통과 (25.50ms, 77.9MB)
테스트 6 〉	통과 (437.48ms, 80.8MB)
테스트 7 〉	통과 (229.69ms, 83MB)
테스트 8 〉	통과 (342.05ms, 82.4MB)
테스트 9 〉	통과 (2127.81ms, 98.5MB)
테스트 10 〉	실패 (시간 초과)
테스트 11 〉	실패 (시간 초과)
테스트 12 〉	실패 (시간 초과)
테스트 13 〉	실패 (시간 초과)
테스트 14 〉	실패 (시간 초과)
테스트 15 〉	실패 (시간 초과)
테스트 16 〉	실패 (시간 초과)
테스트 17 〉	통과 (338.21ms, 198MB)
테스트 18 〉	통과 (2.29ms, 78.3MB)
테스트 19 〉	통과 (3.32ms, 71.2MB)
테스트 20 〉	통과 (3.47ms, 73.5MB)
테스트 21 〉	통과 (3.48ms, 77.1MB)
테스트 22 〉	통과 (3.36ms, 78MB)
테스트 23 〉	통과 (3.23ms, 72.7MB)
테스트 24 〉	실패 (시간 초과)
테스트 25 〉	실패 (시간 초과)
테스트 26 〉	실패 (시간 초과)
테스트 27 〉	실패 (시간 초과)
테스트 28 〉	실패 (시간 초과)
테스트 29 〉	실패 (시간 초과)
테스트 30 〉	실패 (시간 초과)
테스트 31 〉	통과 (2.71ms, 76.9MB)
테스트 32 〉	통과 (2.64ms, 73.4MB)
테스트 33 〉	통과 (2.19ms, 75.2MB)
테스트 34 〉	통과 (2.35ms, 73.7MB)

수정된 코드


문제의 경우 정렬된 수열이 주어지므로, 투 포인터를 이용하면 문제를 해결 할 수 있을것이라고 판단했다. 

start, end 인덱스를 가지는 변수를 선언한 뒤, 덧셈한 값이 k보다 작으면 end 인덱스의 값을 더하고, end 인덱스를 늘려준다. 만약 덧셈한 값이 k 보다 크다면, start 인덱스의 값을 빼주고, start 인덱스를 한칸 올려준다.

연산이 끝나면, 가장 길이가 짧은 수열을 리턴해야 하므로 정렬 후 리턴해줬다. 

코드

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;

class Solution {
    public int[] solution(int[] sequence, int k) {
        int[] answer;
        ArrayList<int[]> list = new ArrayList<>();
        // k 보다큰 값 제외
        int sum = 0;
        int start = 0;
        int end  = 0;
        while (start <= end && end < sequence.length) {
            if (sum == k) {
                list.add(new int[]{start,end-1});
            }
            if (sum + sequence[end] <= k) {
                sum += sequence[end++];
            } else {
                sum -= sequence[start++];
            }
        }
        if (sum == k) {
            list.add(new int[]{start,end-1});
        }
        list.sort(new Comparator<int[]>() {
            @Override
            public int compare(int[] o1, int[] o2) {
                return (o1[1]- o1[0]) - (o2[1] - o2[0]);
            }
        });

        answer = list.get(0);
        return answer;
    }
}

문제

시간 제한 메모리 제한 제출 정답 맞힌 사람 정답 비율

2 초 256 MB 87846 23673 14467 24.067%

문제

그래프의 정점의 집합을 둘로 분할하여, 각 집합에 속한 정점끼리는 서로 인접하지 않도록 분할할 수 있을 때, 그러한 그래프를 특별히 이분 그래프 (Bipartite Graph) 라 부른다.

그래프가 입력으로 주어졌을 때, 이 그래프가 이분 그래프인지 아닌지 판별하는 프로그램을 작성하시오.

입력

입력은 여러 개의 테스트 케이스로 구성되어 있는데, 첫째 줄에 테스트 케이스의 개수 K가 주어진다. 각 테스트 케이스의 첫째 줄에는 그래프의 정점의 개수 V와 간선의 개수 E가 빈 칸을 사이에 두고 순서대로 주어진다. 각 정점에는 1부터 V까지 차례로 번호가 붙어 있다. 이어서 둘째 줄부터 E개의 줄에 걸쳐 간선에 대한 정보가 주어지는데, 각 줄에 인접한 두 정점의 번호 u, v (u ≠ v)가 빈 칸을 사이에 두고 주어진다.

출력

K개의 줄에 걸쳐 입력으로 주어진 그래프가 이분 그래프이면 YES, 아니면 NO를 순서대로 출력한다.

제한

  • 2 ≤ K ≤ 5
  • 1 ≤ V ≤ 20,000
  • 1 ≤ E ≤ 200,000

풀이

이분 그래프란?

그래프의 정점의 집합을 둘로 분할하여, 각 집합에 속한 정점끼리는 서로 인접하지 않도록 분할할 수 있어야 한다.

나의 경우 bfs 탐색을 통해 depth가 증가할 때 마다 colors 배열의 값을 토글시켜줬다. 만약 현재 정점이 방문 가능한 정점의 인덱스가 colors 배열에 값이 있다면 현재 정점의 인덱스와 비교하여 같은 값을 가지고 있다면 이분 그래프가 아니다.

만약 colors 배열의 새로운 정점의 인덱스 위치에 값이 0이라면, 현재 인덱스의 값을 토글하여 저장한다.

코드

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.Queue;
import java.util.StringTokenizer;

public class Main {
    static int[] colors;
    static ArrayList<Integer>[] arrayLists;
    static int V;
    static int E;
    static String res;
    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        StringBuilder sb = new StringBuilder();
        StringTokenizer st = new StringTokenizer(br.readLine());

        int testCaseCount =  Integer.parseInt(st.nextToken());
        
        for (int i = 0; i < testCaseCount; i++) {
            st = new StringTokenizer(br.readLine());
            V = Integer.parseInt(st.nextToken());
            E = Integer.parseInt(st.nextToken());
            colors = new int[V];
            arrayLists = new ArrayList[V];
            for (int j = 0; j < V; j++) {
                arrayLists[j] = new ArrayList<>();
            }
            for (int j = 0; j < E; j++) {
                st = new StringTokenizer(br.readLine());
                int first = Integer.parseInt(st.nextToken())-1;
                int second = Integer.parseInt(st.nextToken())-1;
                arrayLists[first].add(second);
                arrayLists[second].add(first);
            }
            res = "YES";
            for (int j = 0; j < V; j++) {
                if (colors[j] == 0)
                    bfs(j);
            }
            sb.append(res).append("\\n");
        }
        System.out.println(sb);
    }
    static void bfs(int v) {
        Queue<Integer> queue = new LinkedList<>();
        queue.add(v);
        colors[v] = 1;
        while (!queue.isEmpty()) {
            int val = queue.poll();
            for (int vertex : arrayLists[val]) {
                if (colors[vertex] == 0) { // 0이면 색칠 안된 곳
                    colors[vertex] = colors[val] * -1;
                    queue.add(vertex);
                }
                if (colors[vertex] == colors[val]) {
                    res = "NO";
                    return;
                }
            }
        }
    }
}

문제

시간 제한 메모리 제한 제출 정답 맞힌 사람 정답 비율

1 초 256 MB 37117 9871 6578 24.587%

문제

상근이는 빈 공간과 벽으로 이루어진 건물에 갇혀있다. 건물의 일부에는 불이 났고, 상근이는 출구를 향해 뛰고 있다.

매 초마다, 불은 동서남북 방향으로 인접한 빈 공간으로 퍼져나간다. 벽에는 불이 붙지 않는다. 상근이는 동서남북 인접한 칸으로 이동할 수 있으며, 1초가 걸린다. 상근이는 벽을 통과할 수 없고, 불이 옮겨진 칸 또는 이제 불이 붙으려는 칸으로 이동할 수 없다. 상근이가 있는 칸에 불이 옮겨옴과 동시에 다른 칸으로 이동할 수 있다.

빌딩의 지도가 주어졌을 때, 얼마나 빨리 빌딩을 탈출할 수 있는지 구하는 프로그램을 작성하시오.

입력

첫째 줄에 테스트 케이스의 개수가 주어진다. 테스트 케이스는 최대 100개이다.

각 테스트 케이스의 첫째 줄에는 빌딩 지도의 너비와 높이 w와 h가 주어진다. (1 ≤ w,h ≤ 1000)

다음 h개 줄에는 w개의 문자, 빌딩의 지도가 주어진다.

  • '.': 빈 공간
  • '#': 벽
  • '@': 상근이의 시작 위치
  • '*': 불

각 지도에 @의 개수는 하나이다.

출력

각 테스트 케이스마다 빌딩을 탈출하는데 가장 빠른 시간을 출력한다. 빌딩을 탈출할 수 없는 경우에는 "IMPOSSIBLE"을 출력한다.

풀이

BFS로 풀 수 있는 문제였다.

  1. 배열을 벽, 불, 상근이, 빈 공간 으로 나눠서 값을 업데이트 해준다.
  2. 움직일 수 있는 사람이 있는지 확인
  3. 현재 시점에 불들을 4 방향으로 불을 퍼뜨린다 (시간이 없을 경우 한번에 불 다붙이고 끝나버림)
  4. 현재 시점에 사람을 4 방향으로 이동시킨다.
  5. 만약 사람이 배열의 끝 부분에 도착했다면 가장 빨리 도착한 경우 업데이트 해준다.

푸는데 중요했던 부분은 두가지가 있었다.

불이 2개가 붙어있다면, 주기마다 2개의 불을 다 이동시켜야 하는 것

빌딩을 탈출하는데에 가장 빠른 시간을 출력하는 것

 

package com.company.baekjoon;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.LinkedList;
import java.util.Queue;

public class B5427 {
    static final int WALL = -2;
    static final int FIRE = -1;
    static final int EMPTY_SPACE = 0;
    static final int PERSON = 1;

    static int[] dx = new int[] {-1,1,0,0};
    static int[] dy = new int[] {0,0,-1,1};
    static int[][] graph;
    static Queue<int[]> fires = new LinkedList<>();
    static Queue<int[]> person = new LinkedList<>();
    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        StringBuilder sb = new StringBuilder();
        int T = Integer.parseInt(br.readLine());

        for (int i = 0; i < T; i++) {
            String[] size = br.readLine().split(" ");
            int w = Integer.parseInt(size[0]);
            int h = Integer.parseInt(size[1]);
            graph = new int[h][w];
            fires.clear();
            person.clear();
            int answer = Integer.MAX_VALUE;
            int time = 0;
            for (int j = 0; j < h; j++) {
                char[] s = br.readLine().toCharArray();
                for (int k = 0; k < s.length; k++) {
                    if (s[k] == '#') {
                        graph[j][k] = WALL;
                    } else if (s[k] == '.') {
                        graph[j][k] = EMPTY_SPACE;
                    } else if (s[k] == '*') {
                        graph[j][k] = FIRE;
                        fires.add(new int[] {j,k,0});
                    } else {
                        graph[j][k] = PERSON;
                        person.add(new int[]{j,k,0});
                    }
                }
            }
            // 불 먼저 움직이고 사람 움직이기
            while (!person.isEmpty()) {
                while (fires.peek() != null && fires.peek()[2] == time ) {
                    int[] fire = fires.poll();
                    for (int j = 0; j < dx.length; j++) {
                        int cy = fire[0] + dy[j];
                        int cx = fire[1] + dx[j];

                        if (cx < 0 || cy < 0 || cx >= w || cy >= h) continue;
                        if (graph[cy][cx] == FIRE) continue;
                        if (graph[cy][cx] != WALL) {
                            graph[cy][cx] = FIRE;
                            fires.add(new int[]{cy, cx, fire[2] + 1});
                        }
                    }
                }

                while (person.peek() != null && person.peek()[2] == time) {
                    int[] p = person.poll();
                    for (int j = 0; j < dx.length; j++) {
                        int cy = p[0] + dy[j];
                        int cx = p[1] + dx[j];

                        if (cx < 0 || cy < 0 || cx >= w || cy >= h) {
                            answer = Math.min(answer,p[2]);
                            break;
                        }
                        if (graph[cy][cx] == EMPTY_SPACE) {
                            graph[cy][cx] = PERSON;
                            person.add(new int[]{cy, cx, p[2] + 1});
                        }
                    }
                }
                time++;
            }
            if (answer == Integer.MAX_VALUE)
                sb.append("IMPOSSIBLE").append("\n");
            else
                sb.append(answer+1).append("\n");
        }
        System.out.println(sb);
    }
}

문제

시간 제한 메모리 제한 제출 정답 맞힌 사람 정답 비율

1 초 (추가 시간 없음) 1024 MB 11094 4316 2704 35.514%

문제

상어 중학교의 코딩 동아리에서 게임을 만들었다. 이 게임은 크기가 N×N인 격자에서 진행되고, 초기에 격자의 모든 칸에는 블록이 하나씩 들어있고, 블록은 검은색 블록, 무지개 블록, 일반 블록이 있다. 일반 블록은 M가지 색상이 있고, 색은 M이하의 자연수로 표현한다. 검은색 블록은 -1, 무지개 블록은 0으로 표현한다. (i, j)는 격자의 i번 행, j번 열을 의미하고, |r1 - r2| + |c1 - c2| = 1을 만족하는 두 칸 (r1, c1)과 (r2, c2)를 인접한 칸이라고 한다.

블록 그룹은 연결된 블록의 집합이다. 그룹에는 일반 블록이 적어도 하나 있어야 하며, 일반 블록의 색은 모두 같아야 한다. 검은색 블록은 포함되면 안 되고, 무지개 블록은 얼마나 들어있든 상관없다. 그룹에 속한 블록의 개수는 2보다 크거나 같아야 하며, 임의의 한 블록에서 그룹에 속한 인접한 칸으로 이동해서 그룹에 속한 다른 모든 칸으로 이동할 수 있어야 한다. 블록 그룹의 기준 블록은 무지개 블록이 아닌 블록 중에서 행의 번호가 가장 작은 블록, 그러한 블록이 여러개면 열의 번호가 가장 작은 블록이다.

오늘은 이 게임에 오토 플레이 기능을 만드려고 한다. 오토 플레이는 다음과 같은 과정이 블록 그룹이 존재하는 동안 계속해서 반복되어야 한다.

  1. 크기가 가장 큰 블록 그룹을 찾는다. 그러한 블록 그룹이 여러 개라면 포함된 무지개 블록의 수가 가장 많은 블록 그룹, 그러한 블록도 여러개라면 기준 블록의 행이 가장 큰 것을, 그 것도 여러개이면 열이 가장 큰 것을 찾는다.
  2. 1에서 찾은 블록 그룹의 모든 블록을 제거한다. 블록 그룹에 포함된 블록의 수를 B라고 했을 때, B점을 획득한다.
  3. 2
  4. 격자에 중력이 작용한다.
  5. 격자가 90도 반시계 방향으로 회전한다.
  6. 다시 격자에 중력이 작용한다.

격자에 중력이 작용하면 검은색 블록을 제외한 모든 블록이 행의 번호가 큰 칸으로 이동한다. 이동은 다른 블록이나 격자의 경계를 만나기 전까지 계속 된다.

다음은 N = 5, M = 3인 경우의 예시이다.

2 2 -1 3 1

3 3 2 0 -1
0 0 0 1 2
-1 3 1 3 2
0 3 2 2 1

여기서 찾을 수 있는 크기가 가장 큰 블록 그룹을 다음과 같이 빨간색으로 표시했다.

2 2 -1 3 1

3 3 2 0 -1
0 0 0 1 2
-1 3 1 3 2
0 3 2 2 1

블록 그룹이 제거되면 다음과 같이 변하고, 점수 82점을 획득한다.

2 2 -1 3 1

    2 0 -1
      1 2
-1   1 3 2
    2 2 1

중력이 작용하면 다음과 같이 변한다.

-1 3 1

      0 -1
2   2 1 2
-1   1 3 2
  2 2 2 1

90도 반시계방향으로 회전한 결과는 다음과 같다.

1 -1 2 2 1

3 0 1 3 2
-1   2 1 2
        2
    2 -1  

다시 여기서 중력이 작용하면 다음과 같이 변한다.

1 -1

3   2 2 1
-1   1 3 2
    2 1 2
  0 2 -1 2

오토 플레이가 모두 끝났을 때 획득한 점수의 합을 구해보자.

입력

첫째 줄에 격자 한 변의 크기 N, 색상의 개수 M이 주어진다.

둘째 줄부터 N개의 줄에 격자의 칸에 들어있는 블록의 정보가 1번 행부터 N번 행까지 순서대로 주어진다. 각 행에 대한 정보는 1열부터 N열까지 순서대로 주어진다. 입력으로 주어지는 칸의 정보는 -1, 0, M이하의 자연수로만 이루어져 있다.

출력

첫째 줄에 획득한 점수의 합을 출력한다.

제한

  • 1 ≤ N ≤ 20
  • 1 ≤ M ≤ 5

풀이

소요 시간

100분

문제에 제시된 오토 플레이 기능을 그대로 구현하면 된다.

  1. BFS를 통해 가장 큰 블록 그룹을 구한다.
  2. 블록 그룹을 제거한다. (EMPTY_BLOCK 으로 마킹했다.)
  3. 중력을 적용한다
  4. 90도 반시계 방향으로 회전시킨다.
  5. 중력을 적용한다.
  6. 1~5를 반복한다. 만약 1번 수행 후 가장 큰 블록 그룹의 블록 갯수가 2개 미만이라면 종료한다.

헤맸던 부분

블록 그룹의 기준 블록은 무지개 블록이 아닌 블록 중에서 행의 번호가 가장 작은 블록, 그러한 블록이 여러개면 열의 번호가 가장 작은 블록이다.

이거 잘못 읽어서 행 길이, 열 길이로 구했다가 한 20분 날려먹었다 문제 잘읽자..

코드

package com.company.baekjoon;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.Queue;
import java.util.StringTokenizer;

public class B21609 {
    static int[] dx = new int[] {-1,1,0,0};
    static int[] dy = new int[] {0,0,-1,1};

    static int N;
    static int M;
    static int[][] arr;
    static boolean[][] visited;
    static int answer = 0;

    static int cnt = 0; // 블록 갯수
    static int rainbowCnt = 0; // 무지개 블록 갯수
    static int targetI = 0; // 행 번호
    static int targetJ = 0; // 열 번호
    static int target = 0;
    static int EMPTY_BLOCK = -2;
    static ArrayList<int[]> targetList = new ArrayList<>();
    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        StringTokenizer st = new StringTokenizer(br.readLine());

        N = Integer.parseInt(st.nextToken());
        M = Integer.parseInt(st.nextToken());

        arr = new int[N][N];
        visited = new boolean[N][N];

        for (int i = 0; i < N; i++) {
            st = new StringTokenizer(br.readLine());
            for (int j = 0; j < N; j++) {
                arr[i][j] = Integer.parseInt(st.nextToken());
            }
        }

        while (true) {
            visited = new boolean[N][N];
            cnt = 0; // 블록 갯수
            rainbowCnt = 0; // 무지개 블록 갯수
            targetI = 0; // 행 갯수
            targetJ = 0; // 열 갯수
            target = 0;
            targetList.clear();
            // BFS로 가장 큰 블록 탐색
            for (int i = 0; i < N; i++) {
                for (int j = 0; j < N; j++) {
                    if (!visited[i][j] && arr[i][j] != -1 && arr[i][j] != 0 && arr[i][j] != EMPTY_BLOCK) {
                        visited[i][j] = true;
                        bfs(i,j);

                    }
                }
            }

            if (cnt < 2) break;

            answer += cnt*cnt;

            // 가장 큰 블록 없애기
            setBlockEmpty();

            // 블록에 중력 적용하기
            gravity();

            // 90도 반시계 방향 회전
            rotation();

            // 블록에 중력 적용하기
            gravity();
        }
        System.out.println(answer);
    }
    public static void bfs(int i, int j) {
        int cCnt = 1; // 블록 갯수
        int cRainbowCnt = 0; // 무지개 블록 갯수
        int cTargetI = i; // 행 번호
        int cTargetJ = j; // 열 번호
        int cTarget = arr[i][j];
        ArrayList<int[]> cTargetList = new ArrayList<>();
        cTargetList.add(new int[] {i,j});
        Queue<int[]> queue = new LinkedList<>();
        queue.add(new int[] {i,j});
        while (!queue.isEmpty()) {
            int[] value = queue.poll();

            for (int k = 0; k < dx.length; k++) {
                int cx = value[0] + dx[k];
                int cy = value[1] + dy[k];

                if (cx < 0 || cy < 0 || cx >= N || cy >= N) continue;
                if (visited[cx][cy]) continue;
                if (arr[i][j] == arr[cx][cy]) {
                    cCnt++;
                    queue.add(new int[] {cx, cy});
                    cTargetList.add(new int[] {cx,cy});
                    visited[cx][cy] = true;
                } else if (arr[cx][cy] == 0) {
                    cCnt++;
                    cRainbowCnt++;
                    queue.add(new int[] {cx, cy});
                    cTargetList.add(new int[] {cx,cy});
                    visited[cx][cy] = true;
                }
            }
        }
        if (cTargetList.size() < 2) return;
        selectTarget(cCnt, cRainbowCnt, cTargetI, cTargetJ, cTarget, cTargetList);

        for (int k = 0; k < cTargetList.size(); k++) {
            // 타겟이 선정되고 난 후 값이 0인 위치는 공유 가능하므로 다시 visited를 false로 변경해준다.
            int[] t = cTargetList.get(k);
            if (arr[t[0]][t[1]] == 0)
                visited[t[0]][t[1]] = false;
        }

    }
    public static void selectTarget(int cCnt, int cRainbowCnt, int cTargetI, int cTargetJ, int cTarget, ArrayList<int[]> cTargetList) {
        if (cCnt> cnt) {
            cnt = cCnt;
            rainbowCnt = cRainbowCnt;
            targetI = cTargetI;
            targetJ = cTargetJ;
            target = cTarget;
            targetList = cTargetList;
        } else if (cCnt == cnt) {
            if (cRainbowCnt > rainbowCnt) {
                cnt = cCnt;
                rainbowCnt = cRainbowCnt;
                targetI = cTargetI;
                targetJ = cTargetJ;
                target = cTarget;
                targetList = cTargetList;
            } else if (cRainbowCnt == rainbowCnt) {
                if (cTargetI > targetI) {
                    cnt = cCnt;
                    rainbowCnt = cRainbowCnt;
                    targetI = cTargetI;
                    targetJ = cTargetJ;
                    target = cTarget;
                    targetList = cTargetList;
                } else if (cTargetI == targetI) {
                    if (cTargetJ > targetJ) {
                        cnt = cCnt;
                        rainbowCnt = cRainbowCnt;
                        targetI = cTargetI;
                        targetJ = cTargetJ;
                        target = cTarget;
                        targetList = cTargetList;
                    }
                }
            }
        }
    }
    public static void setBlockEmpty() {
        for (int i = 0; i < targetList.size(); i++) {
            int[] target = targetList.get(i);
            arr[target[0]][target[1]] = EMPTY_BLOCK;
        }
    }
    public static void gravity() {
        for(int i = 0; i < N; ++i)
        {
            for(int j = N-1; j >= 0; --j)
            {
                if(arr[j][i] == EMPTY_BLOCK || arr[j][i] == -1) continue;
                int idx = j+1;
                while(true)
                {
                    if(idx == N) break;
                    if(arr[idx][i] == EMPTY_BLOCK) idx++;
                    else break;
                }
                if(idx == j+1) continue;
                arr[idx-1][i] = arr[j][i];
                arr[j][i] = EMPTY_BLOCK;
            }
        }
    }
    public static void rotation() {
        int [][] tmp = new int[N][N];
        for(int i = 0; i < N; ++i)
        {
            for(int j = 0; j < N; ++j)
            {
                tmp[N-j-1][i] = arr[i][j];
            }
        }
        for(int i = 0; i < N; ++i)
        {
            System.arraycopy(tmp[i],0,arr[i],0,N);
        }
    }
}

문제

시간 제한 메모리 제한 제출 정답 맞힌 사람 정답 비율

2 초 128 MB 3585 1277 1001 37.323%

문제

한글 프로그램의 메뉴에는 총 N개의 옵션이 있다. 각 옵션들은 한 개 또는 여러 개의 단어로 옵션의 기능을 설명하여 놓았다. 그리고 우리는 위에서부터 차례대로 각 옵션에 단축키를 의미하는 대표 알파벳을 지정하기로 하였다. 단축키를 지정하는 법은 아래의 순서를 따른다.

  1. 먼저 하나의 옵션에 대해 왼쪽에서부터 오른쪽 순서로 단어의 첫 글자가 이미 단축키로 지정되었는지 살펴본다. 만약 단축키로 아직 지정이 안 되어있다면 그 알파벳을 단축키로 지정한다.
  2. 만약 모든 단어의 첫 글자가 이미 지정이 되어있다면 왼쪽에서부터 차례대로 알파벳을 보면서 단축키로 지정 안 된 것이 있다면 단축키로 지정한다.
  3. 어떠한 것도 단축키로 지정할 수 없다면 그냥 놔두며 대소문자를 구분치 않는다.
  4. 위의 규칙을 첫 번째 옵션부터 N번째 옵션까지 차례대로 적용한다.

입력

첫째 줄에 옵션의 개수 N(1 ≤ N ≤ 30)이 주어진다. 둘째 줄부터 N+1번째 줄까지 각 줄에 옵션을 나타내는 문자열이 입력되는데 하나의 옵션은 5개 이하의 단어로 표현되며, 각 단어 역시 10개 이하의 알파벳으로 표현된다. 단어는 공백 한 칸으로 구분되어져 있다.

출력

N개의 줄에 각 옵션을 출력하는데 단축키로 지정된 알파벳은 좌우에 [] 괄호를 씌워서 표현한다.

풀이

시간 복잡도

N = 30, 단어 갯수 = 5, 단어 길이 = 10 이므로, 시간제한 2초에는 충분히 들어올 수 있다.

  1. 문자열을 단어 단위로 분리한다.
  2. 단어의 첫번째 글자가 단축키가 될 수 있다면 해당 문자열 배열의 값을 변경 함.
  3. 만약 2번 과정에서 단축키를 찾지 못했다면 문자열 순서대로 단축키로 사용가능한 값을 찾아서 해당 문자열 배열의 값을 변경 함.
  4. 분리한 문자열을 합쳐서 출력

코드

package com.company.baekjoon;

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

public class B1283 {
    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        StringBuilder sb = new StringBuilder();
        int N = Integer.parseInt(br.readLine());
        HashSet<Character> set = new HashSet<>();

        StringBuilder result = new StringBuilder();
        for (int i = 0; i < N; i++) {
            boolean hasCommand = false;
            String[] input = br.readLine().split(" ");

            for (int j = 0; j < input.length; j++) {
                if (!set.contains(Character.toLowerCase(input[j].charAt(0))) && !hasCommand) {
                    set.add(Character.toLowerCase(input[j].charAt(0)));
                    result.append(input[j]);
                    result.insert(0, "[");
                    result.insert(2, "]");
                    input[j] = result.toString();
                    hasCommand = true;
                    result.setLength(0);

                }
            }
            if (!hasCommand) {
                for (int j = 0; j < input.length; j++) {
                    for (int k = 0; k < input[j].length(); k++) {
                        if (!set.contains(Character.toLowerCase(input[j].charAt(k))) && !hasCommand) {
                            set.add(Character.toLowerCase(input[j].charAt(k)));
                            result.append(input[j]);
                            result.insert(k, "[");
                            result.insert(k+2, "]");
                            input[j] = result.toString();
                            hasCommand = true;
                            result.setLength(0);
                        }
                    }
                }
            }
            for (int j = 0; j < input.length; j++) {
                if (j == input.length -1) sb.append(input[j]);
                else sb.append(input[j]).append(" ");
            }
            sb.append("\\n");
        }
        System.out.println(sb);
    }
}

문제

시간 제한 메모리 제한 제출 정답 맞힌 사람 정답 비율

1 초 512 MB 15785 9277 6176 57.095%

문제

길이가 N인 컨베이어 벨트가 있고, 길이가 2N인 벨트가 이 컨베이어 벨트를 위아래로 감싸며 돌고 있다. 벨트는 길이 1 간격으로 2N개의 칸으로 나뉘어져 있으며, 각 칸에는 아래 그림과 같이 1부터 2N까지의 번호가 매겨져 있다.

벨트가 한 칸 회전하면 1번부터 2N-1번까지의 칸은 다음 번호의 칸이 있는 위치로 이동하고, 2N번 칸은 1번 칸의 위치로 이동한다. i번 칸의 내구도는 Ai이다. 위의 그림에서 1번 칸이 있는 위치를 "올리는 위치", N번 칸이 있는 위치를 "내리는 위치"라고 한다.

컨베이어 벨트에 박스 모양 로봇을 하나씩 올리려고 한다. 로봇은 올리는 위치에만 올릴 수 있다. 언제든지 로봇이 내리는 위치에 도달하면 그 즉시 내린다. 로봇은 컨베이어 벨트 위에서 스스로 이동할 수 있다. 로봇을 올리는 위치에 올리거나 로봇이 어떤 칸으로 이동하면 그 칸의 내구도는 즉시 1만큼 감소한다.

컨베이어 벨트를 이용해 로봇들을 건너편으로 옮기려고 한다. 로봇을 옮기는 과정에서는 아래와 같은 일이 순서대로 일어난다.

  1. 벨트가 각 칸 위에 있는 로봇과 함께 한 칸 회전한다.
  2. 가장 먼저 벨트에 올라간 로봇부터, 벨트가 회전하는 방향으로 한 칸 이동할 수 있다면 이동한다. 만약 이동할 수 없다면 가만히 있는다.
  3. 로봇이 이동하기 위해서는 이동하려는 칸에 로봇이 없으며, 그 칸의 내구도가 1 이상 남아 있어야 한다.
  4. 올리는 위치에 있는 칸의 내구도가 0이 아니면 올리는 위치에 로봇을 올린다.
  5. 내구도가 0인 칸의 개수가 K개 이상이라면 과정을 종료한다. 그렇지 않다면 1번으로 돌아간다.

종료되었을 때 몇 번째 단계가 진행 중이었는지 구해보자. 가장 처음 수행되는 단계는 1번째 단계이다.

입력

첫째 줄에 N, K가 주어진다. 둘째 줄에는 A1, A2, ..., A2N이 주어진다.

출력

몇 번째 단계가 진행 중일때 종료되었는지 출력한다.

제한

  • 2 ≤ N ≤ 100
  • 1 ≤ K ≤ 2N
  • 1 ≤ A ≤ 1,000
  • i

풀이

풀이시간 : 140분

문제를 이해하는데 어려웠던 부분

  • “올린다”와 “내린다”의 개념 파악 ⇒ N개 이상 부터(아래 컨베이어 벨트)는 로봇을 올리지 않아도 된다.
  • 벨트가 이동하는 것과 로봇이 이동하는 것은 별개 ⇒ 벨트는 매 루프마다 이동하고, 로봇은 따로 이동가능한지 여부를 따져서 이동
  • 가장 먼저 올라간 로봇 부터 이동 시작 ⇒ N번부터 0번 인덱스까지 로봇 이동가능 여부 판단 해야함 

사용 자료구조

  1. top Conveyor : 큐를 사용하면 좋겠지만, 로봇 이동을 위해 인덱스 접근이 필요하므로 ArrayList 사용
  2. bottom Conveyor : Deque를 사용하여 컨테이너 이동 구현

코드

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

public class Main {
    static int N;
    static int K;

    public static class Belt {
        int durability;
        boolean hasRobot;
        public Belt(int durability) {
            this.durability = durability;
        }

        @Override
        public String toString() {
            return durability+"";
        }
    }
    static ArrayList<Belt> topConvayor = new ArrayList<>();
    static ArrayDeque<Belt> bottomConvayor = new ArrayDeque<>();

    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        StringTokenizer st = new StringTokenizer(br.readLine());

        N = Integer.parseInt(st.nextToken());
        K = Integer.parseInt(st.nextToken());
        int loopCount = 0;
        st = new StringTokenizer(br.readLine());
        for (int i = 0; i < N; i++) {
            topConvayor.add(new Belt(Integer.parseInt(st.nextToken())));
        }
        for (int i = 0; i < N; i++) {
            bottomConvayor.add(new Belt(Integer.parseInt(st.nextToken())));
        }
        
        while (K > 0) {
            loopCount++;
            moveBelt();
            lowerRobot();
            moveRobot();
            lowerRobot();
            raiseRobot();

        }
        System.out.println(loopCount);
    }
    public static void moveBelt() {
        topConvayor.add(0, bottomConvayor.pollLast());
        bottomConvayor.addFirst(topConvayor.get(N));
        topConvayor.remove(N);
    }
    public static void moveRobot() {
        for (int i = N-1; i > 0; i--) {
            Belt currentBelt = topConvayor.get(i-1);
            Belt nextBelt = topConvayor.get(i);
            if (currentBelt.hasRobot && !nextBelt.hasRobot && nextBelt.durability >= 1) {
                // 현재 벨트위에 로봇이 있고, 다음 벨트에 로봇이 없으며 내구도가 1이상이라면 로봇을 이동시킬 수 있다.
                currentBelt.hasRobot = false;
                nextBelt.hasRobot = true;
                nextBelt.durability -= 1;
                if (nextBelt.durability == 0) {
                    K--;
                }
            }

        }
    }
    public static void raiseRobot() {
        Belt b = topConvayor.get(0);
        if (!b.hasRobot && b.durability >= 1) { // 0번째 벨트에 로봇이 없고, 내구도가 1이상이라면 로봇을 올릴 수 있다.
            topConvayor.get(0).hasRobot = true;
            topConvayor.get(0).durability -= 1;
            if (topConvayor.get(0).durability == 0) {
                K--;
            }
        }
    }
    public static void lowerRobot() {
        topConvayor.get(N-1).hasRobot = false;
    }
}

+ Recent posts