Dazzling 개발 노트

[코드트리] 구슬의 이동 (Java) 본문

Algorithm/코드트리

[코드트리] 구슬의 이동 (Java)

dj._.dazzling 2023. 8. 22. 15:42

[코드트리] 구슬의 이동 (Java)

문제

https://www.codetree.ai/cote/13/problems/marble-movement?utm_source=clipboard&utm_medium=text

풀이/후기

스터디 시간에 풀게된 문제이다.

처음엔 쉽다고 생각했는데, 한 칸에 여러개의 구슬이 존재할 때 우선순위에 따라 제거하는 작업이 까다로웠다.

그리고 이 문제를 통해 가장 먼저 느낀 것은 '자바의 한계' 였다.

평소에도 코테 준비하면서 파이썬이 훨씬 간단하다는 것은 알고 있었지만, 이번에 특히나 더 그렇게 생각이 된 것 같다.

(아마도 스터디원이 파이썬을 통해 객체 정렬을 구현한 것이 간단해 보여서 그랬을까..?)

 

아무튼 우선순위에 따라 가장 큰 항목을 남기기는 구현을 할 수 있겠는데,

우선순위에 따른 k개를 유지해야 한다는 것이 좀 어려웠던 것 같다.

이 부분은 정렬을 통해 해결할 수 있는데,

클래스이기 때문에 객체 비교를 이용해 정렬을 해야 한다.

생성한 클래스에서 comparable을 implements 이용해야 한다.

그래서 이 부분도 공부가 필요했다.

 

이 문제는 코드트리 문제 중에서도 제출한 사람이 적은 문제인 것 같다.

자바 검색을 해도 안나오는 것을 보니 이상하다고 생각했는데,,,

자바로 제출한 사람이 나밖에 없음ㅋㅋ

신기한 경험이었다.

그래도 코드트리에서 해설 코드를 제공해주어서 다행이지

혼자 고민하다가 삽질을 하루종일 할 뻔했다...

그래도 계속 보다보니 익숙해지고

계속 지웠다 썼다 하니 소스코드도 거의 외운 기분이다.

 

부디 나중에는 바로 생각나길...

코드

package CodeTree.Samsung.Simulation;
//코드트리
//구슬의 이동
//https://www.codetree.ai/cote/13/problems/marble-movement/description

import java.io.*;
import java.util.*;

public class marbleMovement {

	static class Circle implements Comparable<Circle> {
		//Collections.sort 사용을 위해 implements Comparable<Circle> 추가
		int v, num, d;

		Circle(int v, int num, int d) {
			this.v = v;
			this.num = num;
			this.d = d;
		}

		@Override
		public int compareTo(Circle other) {
			if(v != other.v) {
				return v - other.v;
			}
	        if(num != other.num) {
	        	return num - other.num;
	        }
	        return d - other.d;
		}
	}

	static int n, m, t, k;
	static int[][] dir = { { -1, 0 }, { 1, 0 }, { 0, 1 }, { 0, -1 } };
	static ArrayList<Circle>[][] grid = new ArrayList[50][50];
	static ArrayList<Circle>[][] nextGrid = new ArrayList[50][50];

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

		n = Integer.parseInt(str.nextToken());
		m = Integer.parseInt(str.nextToken());
		t = Integer.parseInt(str.nextToken());
		k = Integer.parseInt(str.nextToken());

		for (int i = 1; i < n + 1; i++) {
			for (int j = 1; j < n + 1; j++) {
				grid[i][j] = new ArrayList<>();
			}
		}

		for (int i = 1; i < m + 1; i++) {
			str = new StringTokenizer(br.readLine(), " ");
			int r = Integer.parseInt(str.nextToken());
			int c = Integer.parseInt(str.nextToken());
			String inp = str.nextToken();
			int v = Integer.parseInt(str.nextToken());

			int d = 0;
			if (inp.equals("U")) {
				d = 0;
			}
			if (inp.equals("D")) {
				d = 1;
			}
			if (inp.equals("R")) {
				d = 2;
			}
			if (inp.equals("L")) {
				d = 3;
			}

			// 정렬 시 속도 내림차순, 번호 내림차순이 되도록
			// (-속도, -번호, 방향) 순으로 대입
			grid[r][c].add(new Circle(-v, -i, d));

		}

		while (t-- > 0) {
			// nextGrid 초기화
			for (int i = 1; i < n + 1; i++) {
				for (int j = 1; j < n + 1; j++) {
					nextGrid[i][j] = new ArrayList<>();
				}
			}

			// 구슬의 이동
			movingFunc();

			// 구슬의 개수 조정
			selectCircle();

			for (int i = 1; i < n + 1; i++) {
				for (int j = 1; j < n + 1; j++) {
					grid[i][j] = (ArrayList<Circle>) nextGrid[i][j].clone();
				}
			}
		}

		int cnt = 0;
		for (int i = 1; i < n + 1; i++) {
			for (int j = 1; j < n + 1; j++) {
				cnt += grid[i][j].size();
			}
		}

		System.out.println(cnt);

	}

	static boolean inRange(int x, int y) {
		return 1 <= x && x <= n && 1 <= y && y <= n;
	}

	static void movingFunc() {
		for (int i = 1; i < n + 1; i++) {
			for (int j = 1; j < n + 1; j++) {
				for (int tm = 0; tm < grid[i][j].size(); tm++) {
					int v = grid[i][j].get(tm).v;
					int num = grid[i][j].get(tm).num;
					int d = grid[i][j].get(tm).d;

					int tv = -v;
					int cx = i;
					int cy = j;
					int nx = 1;
					int ny = 1;
					while (tv-- > 0) {
						nx = cx + dir[d][0];
						ny = cy + dir[d][1];
						if (!inRange(nx, ny)) {
							if (d == 0)
								d = 1;
							else if (d == 1)
								d = 0;
							else if (d == 2)
								d = 3;
							else if (d == 3)
								d = 2;
							nx = cx + dir[d][0];
							ny = cy + dir[d][1];
						}
						cx = nx;
						cy = ny;
					}

					nextGrid[nx][ny].add(new Circle(v, num, d));

				}
			}
		}
	}

	static void selectCircle() {
		for (int i = 1; i < n + 1; i++) {
			for (int j = 1; j < n + 1; j++) {
				int size = (int) nextGrid[i][j].size();

				if (size >= k) {
					// 우선순위를 위한 정렬
					Collections.sort(nextGrid[i][j]);
					// k개만 남도록 반복
					while ((int) nextGrid[i][j].size() > k) {
						// 가장 마지막에 있는 항목을 제거
						int t = nextGrid[i][j].size() - 1;
						nextGrid[i][j].remove(nextGrid[i][j].size() - 1);
					}
				}
			}
		}
	}
}

TestCase

#3 입력

4 4 4 1
1 1 L 1
1 3 R 2
2 2 U 1
3 2 D 3

 

#3 출력

3

 

Commit

https://github.com/allrightDJ0108/CodingTestStudy/commit/8acd47de157fdfbff2dfc2112258d965138cb85b

참고