알고리즘 문제 풀이/BOJ

[backjoon]3190 뱀 java

v 2021. 9. 9. 16:00

https://www.acmicpc.net/problem/3190

 

3190번: 뱀

 'Dummy' 라는 도스게임이 있다. 이 게임에는 뱀이 나와서 기어다니는데, 사과를 먹으면 뱀 길이가 늘어난다. 뱀이 이리저리 기어다니다가 벽 또는 자기자신의 몸과 부딪히면 게임이 끝난다. 게임

www.acmicpc.net

1. Queue : 뱀의 움직임 관리 Queue<Snake> moveInfo 

2. Deque : 뱀 자체 관리 Deque<Dot> snake

3. int[][] : 사과의 위치 관리 map

4. class Dot : 뱀이나 사과의 위치 값 관리

5. class Snake : 뱀이 움직일 위치 정보 기록

6. move() : 뱀이 움직임에 대한 메서드

뱀이 사과를 먹으면 커지고 안 먹으면 안 커지거나 코너에서의 방향 전환에 대해 생각하기가 조금 어려웠다.
뱀이 사과를 먹으면 커지는 것에 대해서는 앞으로 한 칸 전진.
뱀이 사과를 못 먹은 것에 대해서는 앞으로 한 칸 전진 후, 제일 마지막 부분 제거(deque에서 pollLast)
코너와 같은 곳에서의 방향 전환은 뱀(deque snake)에서 저장되어 있는 값이기에 따로 변경해줄 필요는 없다.
deque를 사용하면 머리와 꼬리만 관리해줄 수 있기 때문에 비교적 복잡하지 않은 코딩이 가능하다고 생각한다.

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

public class Main {
	static int N;
	static Deque<Dot> snake;
	static int[][] map;

	public static void main(String[] args) throws Exception {

		// Input
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		StringTokenizer st;
		st = new StringTokenizer(br.readLine());
		N = Integer.parseInt(st.nextToken());
		st = new StringTokenizer(br.readLine());
		int K = Integer.parseInt(st.nextToken());

		map = new int[N + 1][N + 1];
		for (int i = 0; i < K; i++) {
			st = new StringTokenizer(br.readLine());
			int row = Integer.parseInt(st.nextToken());
			int col = Integer.parseInt(st.nextToken());
			map[row][col] = 1;// 사과있음.
		}

		st = new StringTokenizer(br.readLine());
		K = Integer.parseInt(st.nextToken());
		Queue<Snake> moveInfo = new LinkedList<>();
		for (int i = 0; i < K; i++) {
			st = new StringTokenizer(br.readLine());
			int sec = Integer.parseInt(st.nextToken());
			String dir = st.nextToken();
			moveInfo.add(new Snake(sec, dir));
		}

		int sec = 0;
		int dir = 0;
		snake = new LinkedList<>();
		// 뱀은 1,1에서 출발함! 첫 방향은 오른쪽!
		snake.add(new Dot(1, 1));
		while (true) {
			sec++;
			if (!move(dir)) {
				break;
			}
			
			if (!moveInfo.isEmpty() && moveInfo.peek().sec == sec) {
				Snake cur = moveInfo.poll();
				String curDir = cur.dir;
				if ("D".equals(curDir))
					dir += 5;
				else
					dir += 3;
			}
			dir %= 4;
		}
		System.out.println(sec + 1);
	}

	public static boolean move(int dir) {
		int[][] dirs = { { 0, 1 }, { 1, 0 }, { 0, -1 }, { -1, 0 } };// 시계방향

		int nextR = snake.peekFirst().row + dirs[dir][0];
		int nextC = snake.peekFirst().col + dirs[dir][1];
		for (Dot cur : snake) {
			if (nextR == cur.row && nextC == cur.col)
				return false;
		}
		if (nextR <= 0 || nextC <= 0 || nextR > N || nextC > N)
			return false;

		Dot head = new Dot(nextR, nextC);

		if (map[nextR][nextC] != 1)
			snake.pollLast();
		else {
			map[nextR][nextC] = 0;
		}
		snake.addFirst(head);

		return true;
	}
}

class Dot {
	int row;
	int col;

	Dot(int row, int col) {
		this.row = row;
		this.col = col;
	}
}

class Snake {
	int sec;
	String dir;

	Snake(int sec, String dir) {
		this.sec = sec;
		this.dir = dir;
	}
}

 

반응형