본문 바로가기
알고리즘

[SW Expert Academy] 핀볼게임 - java

by minkang 2021. 8. 31.

https://swexpertacademy.com/main/code/problem/problemDetail.do?contestProbId=AWXRF8s6ezEDFAUo&categoryId=AWXRF8s6ezEDFAUo&categoryType=CODE&problemTitle=sw&orderBy=FIRST_REG_DATETIME&selectCodeLang=ALL&select-1=&pageSize=10&pageIndex=1 

 

SW Expert Academy

SW 프로그래밍 역량 강화에 도움이 되는 다양한 학습 컨텐츠를 확인하세요!

swexpertacademy.com

public class 핀볼게임3 {
	static int N;
	static int map[][];
	static ArrayList<Point> hall[];

	public static void main(String[] args) throws NumberFormatException, IOException {
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		int T = Integer.parseInt(br.readLine());
		for (int test_case = 1; test_case <= T; test_case++) {
			N = Integer.parseInt(br.readLine());
			map = new int[N][N];
			hall = new ArrayList[5];
			for (int i = 0; i < 5; i++) {
				hall[i] = new ArrayList<Point>();
			}
			for (int i = 0; i < N; i++) {
				StringTokenizer st = new StringTokenizer(br.readLine());
				for (int j = 0; j < N; j++) {
					map[i][j] = Integer.parseInt(st.nextToken());
					if (map[i][j] >= 6 && map[i][j] <= 10) {
						hall[map[i][j] - 6].add(new Point(i, j));
					}
				}
			}

			int sum = 0;
			int result = 0;
			for (int i = 0; i < N; i++) {
				for (int j = 0; j < N; j++) {
					if (map[i][j] == 0) {
						for (int d = 0; d < 4; d++) {
							sum = solve(i, j, d);
							if (result < sum) {
								result = sum;
							}
						}
					}
				}
			}

			System.out.println("#" + test_case + " " + result);

		}
	}

	private static int solve(int sx, int sy, int dir) {
		int dx[] = new int[] { -1, 1, 0, 0 };
		int dy[] = new int[] { 0, 0, -1, 1 };
		int nx = sx;
		int ny = sy;
		int cdir = dir;
		int sum = 0;

		int block[][] = new int[][] { 
			{ 0, 0, 0, 0, 0 }, 
			{ 1, 3, 0, 2 }, 
			{ 3, 0, 1, 2 }, { 2, 0, 3, 1 }, { 1, 2, 3, 0 },
				{ 1, 0, 3, 2 } };

		while (true) {
			nx = nx + dx[cdir];
			ny = ny + dy[cdir];

			if (nx < 0 || nx >= N || ny < 0 || ny >= N) {
				sum++;
				if (cdir <= 1) {
					cdir = (cdir + 1) % 2;
				} else {
					cdir = cdir + 1;
					if (cdir == 4) {
						cdir = 2;
					}
				}
				continue;
			} else if (map[nx][ny] >= 1 && map[nx][ny] <= 5) {
				sum++;
				cdir = block[map[nx][ny]][cdir];
				continue;
			} else if (map[nx][ny] >= 6 && map[nx][ny] <= 10) {
				for (int i = 0; i < 2; i++) {
					Point temp = hall[map[nx][ny] - 6].get(i);
					if (temp.x == nx && temp.y == ny) {
						continue;
					} else {
						nx = temp.x;
						ny = temp.y;
						break;
					}
				}
				continue;
			}

			if ((nx == sx && ny == sy) || (map[nx][ny] == -1)) {
				return sum;
			}
		}
	}

	static class Point {
		int x, y;

		public Point(int x, int y) {
			this.x = x;
			this.y = y;
		}
	}
}

오랜만에 SW 모의 역량 문제를 풀어 보았습니다.

프로그래머스와는 유형이 달라서 조금 헤맸었는데요..

주의할 점은 벽에 부딪혀서 돌아온 자리가 원래 자리였으면 바로 종료해야합니다.

웜홀을 ArrayList로 받아 관리하고, 각 블록마다 이동방향을 달리해줘야 하는데

block[][] 배열을 이용해 처리하였습니다.

1번 블록에 아래 방향으로 부딪힐경우 오른쪽 방향으로 변경해주어야 합니다.

예를 들어 1번 블록에 dir 1 (아래)방향으로 부딪힐경우

block[1][1] = 3(오른쪽);

3의 값이 나오도록 초기화 해주었습니다.

int block[][] = new int[][] { 
  { 0, 0, 0, 0, 0 }, 
  { 1, 3, 0, 2 }, 
  { 3, 0, 1, 2 }, 
  { 2, 0, 3, 1 }, 
  { 1, 2, 3, 0 },
  { 1, 0, 3, 2 } 
};