본문 바로가기
알고리즘/문제풀이

[Java] 백준 3190 : 뱀

by abcodef 2022. 6. 25.

🔗 문제 내용

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

 

3190번: 뱀

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

www.acmicpc.net

🌱 문제 풀이 방법

떠오르는 알고리즘이 없어서 특별한 알고리즘을 적용하진 않았다.

방향 계산 하는게 많이 어려웠다.

규칙을 기반으로 구현했다.

 

🤔 공부가 필요한 부분

방향 계산을 잘 할 수 있는 연습을 많이 해야할 것 같다.

💻 코드

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.StringTokenizer;

public class Main_3190_뱀 {
	static int N, sec;
	static int[][] map;
	static int[] command;
	static int[][] move = { { -1, 0 }, { 0, -1 }, { 1, 0 }, { 0, 1 } }; // 상좌하우
	static ArrayList<position> snake;

	static class position {
		int row; // 세로 좌표
		int col; // 가로 좌표

		public position(int row, int col) {
			super();
			this.row = row;
			this.col = col;
		}

	}

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

		N = Integer.parseInt(br.readLine()); // 보드의 크기
		int K = Integer.parseInt(br.readLine()); // 사과의 개수
		map = new int[N + 1][N + 1]; // (1,1)부터 시작

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

		int L = Integer.parseInt(br.readLine());
		command = new int[10001];
		for (int i = 0; i < L; i++) {
			StringTokenizer st = new StringTokenizer(br.readLine());
			int r = Integer.parseInt(st.nextToken());
			if (st.nextToken().charAt(0) == 'L') {
				command[r] = 1;
			} else {
				command[r] = -1;
			}
		}

		snake = new ArrayList<>();
		sec = 0;
		snake.add(new position(1, 1));
		snake_move(1, 1); // 뱀의 시작은 맨위 맨좌측

		System.out.println(sec);

	}

	static void snake_move(int row, int col) {
		int dir = 3; // 뱀은 처음에 오른쪽을 향함
		while (true) {
			sec++; // 초 증가 후 규칙에 따라서 이동
			// 몸 길이를 늘려 다음칸에 위치
			int newrow = row + move[dir][0];
			int newcol = col + move[dir][1];
			// 벽에 닿거나, 자기자신의 몸과 만났는지 확인
			if (!chk(newrow, newcol)) {
				return;
			}
			if (map[newrow][newcol] == 1) { // 사과가 있는 경우
				// 사과가 있다면, 몸 추가 및 사과 제거(꼬리 제거 x)
				snake.add(new position(newrow, newcol));
				map[newrow][newcol] = 0;
			} else {
				// 몸 추가 및 꼬리 제거
				snake.add(new position(newrow, newcol));
				snake.remove(0);
			}
			row = newrow;
			col = newcol;

			// 방향 계산
			dir = (dir + command[sec]) % 4;
			if(dir==-1) dir=3;

		}
	}

	static boolean chk(int r, int c) {
		// 벽 확인
		if (r < 1 || r > N || c < 1 || c > N) {
			return false;
		}
		// 자기자신 몸과 만났는지 확인
		for (int i = 0; i < snake.size(); i++) {
			if (snake.get(i).row == r && snake.get(i).col == c) {
				return false;
			}
		}
		return true;
	}
}

댓글