[문제링크]

 

14938번: 서강그라운드

예은이는 요즘 가장 인기가 있는 게임 서강그라운드를 즐기고 있다. 서강그라운드는 여러 지역중 하나의 지역에 낙하산을 타고 낙하하여, 그 지역에 떨어져 있는 아이템들을 이용해 서바이벌을

www.acmicpc.net

 

0. m 이하의 cost로 방문 가능한 노드가 가장 많은 노드 찾기

  • 다익스트라를 n번 돌리거나, 플로이드-와샬 진행

 

1. 편의를 위해, 갈 수 없는 노드는 큰 값(2000)으로 초기화한다

  • 최대 거리가 15, 노드가 100개이므로 두 노드의 거리는 15*99=1485가 최대값이다

 

2. 노드 간 거리 정보를 저장하고, 플로이드-와샬을 진행해 각 노드간 거리를 구한다

 

3. 각 노드 별 방문 가능한 노드들로부터 획득 아이템 갯수를 종합, 최댓값을 출력한다

 

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

public class Main{
	public static void main(String[] args)throws Exception {
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		
		StringTokenizer st = new StringTokenizer(br.readLine(), " ");
		int n = pint(st.nextToken());
		int m = pint(st.nextToken());
		int r = pint(st.nextToken());
		
		int[][]map=new int[n][n];
		for (int i = 0; i < n; i++) {
			Arrays.fill(map[i], 2000);
		}
		int[] item=new int[n];
		
		st = new StringTokenizer(br.readLine());
		for (int i = 0; i < n; i++) {
			item[i]=pint(st.nextToken());
		}
		
		for (int i = 0; i < r; i++) {
			st = new StringTokenizer(br.readLine());
			int n1 = pint(st.nextToken())-1;
			int n2 = pint(st.nextToken())-1;
			int c = pint(st.nextToken());
			
			map[n1][n2]=c;
			map[n2][n1]=c;
		}

		for (int k = 0; k < n; k++) {
			for (int i = 0; i < n; i++) {
				if(i==k)continue;
				for (int j = 0; j < n; j++) {
					if(i==j)continue;
					map[i][j]=Math.min(map[i][j],map[i][k]+map[k][j]);
				}
			}
		}
		
		int max_item=0;
		for (int i = 0; i < n; i++) {
			map[i][i]=0;
			int temp=0;
			for (int j = 0; j < n; j++) {
				if(map[i][j]<=m) {
					temp+=item[j];
				}
			}
			max_item=Math.max(temp, max_item);
		}
		System.out.println(max_item);
		
	}
	static int pint(String s) {
		return Integer.parseInt(s);
	}
}

결과 화면

[문제링크]

 

14891번: 톱니바퀴

총 8개의 톱니를 가지고 있는 톱니바퀴 4개가 아래 그림과 같이 일렬로 놓여져 있다. 또, 톱니는 N극 또는 S극 중 하나를 나타내고 있다. 톱니바퀴에는 번호가 매겨져 있는데, 가장 왼쪽 톱니바퀴

www.acmicpc.net

 

0. 구현문제. 요구사항을 잘 구현한다

 

1. 톱니바퀴의 연쇄 회전 : 회전 여부를 저장하는 boolean 배열과 재귀로 진행

 

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

public class Main{
	static boolean[][] wheel;
	static boolean[] isTurn;
	public static void main(String[] args)throws Exception {
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		StringTokenizer st;
		
		//s극 : true, n극 : false
		wheel = new boolean[4][8];
		
		for (int i = 0; i < 4; i++) {
			String s = br.readLine();
			for (int j = 0; j < 8; j++) {
				wheel[i][j]=s.charAt(j)-'0'==1?true:false;
			}
		}
		
		int n = pint(br.readLine());
		for (int i = 0; i < n; i++) {
			st = new StringTokenizer(br.readLine(), " ");
			
			int num = pint(st.nextToken())-1;
			int dir = pint(st.nextToken());

			isTurn=new boolean[4];
			turn(num,dir);//1:시계, -1:반시계
		}
		int score=0;
		for (int i = 0; i < 4; i++) {
			if(wheel[i][0])score+=1<<i;
		}
		System.out.println(score);
		
	}
	
	static void turn(int n, int dir) {
		isTurn[n]=true;
		if(n<3 && !isTurn[n+1] && wheel[n][2]!=wheel[n+1][6])turn(n+1, dir==1?-1:1);
		if(n>0 && !isTurn[n-1] && wheel[n][6]!=wheel[n-1][2])turn(n-1, dir==1?-1:1);
		
		if(dir==1) {
			boolean tmp = wheel[n][7];
			for (int i = 7; i > 0; i--) {
				wheel[n][i] = wheel[n][i-1];
			}wheel[n][0]=tmp;
		}
		else {
			boolean tmp = wheel[n][0];
			for (int i = 0; i < 7; i++) {
				wheel[n][i] = wheel[n][i+1];
			}wheel[n][7]=tmp;
		}
	}
	static int pint(String s) {
		return Integer.parseInt(s);
	}
}

결과 화면

[문제링크]

 

16919번: 봄버맨 2

첫째 줄에 R, C, N (1 ≤ R, C ≤ 200, 1 ≤ N ≤ 109)이 주어진다. 둘째 줄부터 R개의 줄에 격자판의 초기 상태가 주어진다. 빈 칸은 '.'로, 폭탄은 'O'로 주어진다.

www.acmicpc.net

 

0. 같은 코드로 봄버맨1(링크)도 해결 가능하다

 

1. 시작 직후를 제외하면, 빈공간을 채운다 - 터진다 - 빈공간을 채운다 - 터진다 - ... 순으로 반복되게 된다

 

2. 특정 시점 x에 폭탄이 놓인다면, x+1시점에는 x-2때 설치된 폭탄들이 터지며 방금 놓인 폭탄 중 일부가 제거된다

  • 이때 제거된 폭탄들은, x시점에 놓인 폭탄들 중 외곽과 닿은 폭탄들이다

 

3. x+2시점에는 새 폭탄이 설치되고, x+3시점에는 x때 설치된 폭탄들이 터지며 x+2폭탄 중 일부가 제거된다

  • 이때 제거된 폭탄들은, x시점에 놓인 폭탄들과 닿은 폭탄들이다

 

4.  즉, 2번에서 제거된 폭탄들과 3번에서 제거된 폭탄들은 그 위치가 같다

  • 얼음의 겉이 1칸 녹은 후, 다시 겉을 얼린다면 처음 그대로의 상태일 것
  • 항상 같은 위치를 제거해가며, 4초를 주기로 무한루프하게 된다

 

5. 즉 시작 직후만 따로 처리해주고, 나머지는 4로 나눈 만큼 진행하면 된다

  • 이때, 폭탄이 설치되는 짝수 시간에는 모든 칸에 폭탄이 위치하므로 진행할 필요 없이 처리 가능하다

 

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

public class Main{
	
	static int[][]map;
	static final int empty=-1;
	public static void main(String[] args)throws Exception {
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		StringBuilder sb = new StringBuilder();
		
		
		StringTokenizer st = new StringTokenizer(br.readLine(), " ");
		int r = pint(st.nextToken());
		int c = pint(st.nextToken());
		int n = pint(st.nextToken());
		map = new int[r][c];

		for (int i = 0; i < r; i++) {
			String s = br.readLine();
			for (int j = 0; j < c; j++) {
				map[i][j]=s.charAt(j)=='.'?empty:0;
			}
		}
		
		if(n==1) {
			for (int i = 0; i < r; i++) {
				for (int j = 0; j < c; j++) {
					sb.append(map[i][j]==empty?'.':'O');
				}sb.append("\n");
			}
		}
		else if(n%2==0) {
			for (int i = 0; i < r; i++) {
				for (int j = 0; j < c; j++) {
					sb.append("O");
				}sb.append("\n");
			}
		}
		else {
			n=n%4+4;
			for(int i = 2; i <= n; i++) {
				if(i%2==0) {
					set(true, i);
				}
				else {
					set(false,i);
				}
			}

			for (int i = 0; i < r; i++) {
				for (int j = 0; j < c; j++) {
					sb.append(map[i][j]==empty?'.':'O');
				}sb.append("\n");
			}
		}
		
		System.out.println(sb);
	}
	
	static void set(boolean mode, int time) {
		if(mode) {//set
			for (int i = 0; i < map.length; i++) {
				for (int j = 0; j < map[0].length; j++) {
					if(map[i][j]==empty)map[i][j]=time;
				}
			}
		}
		else {
			for (int i = 0; i < map.length; i++) {
				for (int j = 0; j < map[0].length; j++) {
					if(map[i][j]==time-3)bomb(i,j,time-3);
				}
			}
		}
	}
	static void bomb(int x, int y, int time) {
		map[x][y]=empty;
		if(y<map[0].length-1 && map[x][y+1]!=time)map[x][y+1]=empty;
		if(y>0 && map[x][y-1]!=time)map[x][y-1]=empty;
		if(x < map.length-1 && map[x+1][y]!=time)map[x+1][y]=empty;
		if(x>0 &&map[x-1][y]!=time)map[x-1][y]=empty;
	}
	
	static int pint(String s) {
		return Integer.parseInt(s);
	}
}

결과 화면

[문제링크]

 

4256번: 트리

첫째 줄에 테스트 케이스의 개수 T가 주어진다. 각 테스트 케이스의 첫째 줄에는 노드의 개수 n이 주어진다. (1 ≤ n ≤ 1,000) BT의 모든 노드에는 1부터 n까지 서로 다른 번호가 매겨져 있다. 다음

www.acmicpc.net

 

1. 현재 노드 x를 기준으로, 전위 순회는 x-[왼쪽]-[오른쪽] 의 순서로, 중위 순회는 [왼쪽]-x-[오른쪽]의 순서로 만들어진다

 

2. 즉, 전위 순회 결과의 첫 노드를 기준으로, 중위 순회의 왼쪽과 오른쪽을 분리할 수 있다.

 

3. 또한 왼쪽과 오른쪽 subtree에 대해서도 동일한 작업으로 분리할 수 있다.

  • 최종적으로 tree의 크기가 1이 되면, leaf 노드가 된다

 

4. tree를 입력받아, root 노드를 만들어 반환하는 함수를 만들 수 있다.

  • 두 자식 노드는 동일 함수에 left/right subtree에 대해 재귀 돌려 구할 수 있다.

 

5. 이때 재귀 순서를 왼쪽->오른쪽으로 진행하면, 전위 순회와 진행 순서가 일치하게 된다

  • 즉, 매 재귀 단계마다 전위순회의 다음번 노드가 곧 root노드가 된다 (전역변수로 관리)
  • 중위 순회의 left/right만 관리하면 된다

 

6. 복원한 원형 tree로부터 후위 순회 결과를 얻어낸다

 

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

public class Main{
	
	static class node{
		int num;
		node left;
		node right;
		node(int num){
			this.num=num;
		}
	}
	static int cnt;
	static int[] pre;
	static int[] in;
	static StringBuilder sb;
	public static void main(String[] args)throws Exception {
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		
		int tc = pint(br.readLine());
		for (int test = 1; test <= tc; test++) {
			int n = pint(br.readLine());
			pre = new int[n];
			in = new int[n];
			cnt=0;
			StringTokenizer st = new StringTokenizer(br.readLine(), " ");
			StringTokenizer st2 = new StringTokenizer(br.readLine(), " ");
			for (int j = 0; j < n; j++) {
				pre[j]=pint(st.nextToken());
				in[j]=pint(st2.nextToken());
			}
			
			node head = restore(0, n); //restore original tree
			
			sb = new StringBuilder();
			postorder(head);
			System.out.println(sb);
		}
	}
	
	static node restore(int s, int e) {
		if(s==e)return null; //leaf node
		int cur = pre[cnt++]; //head of current subtree
		node n = new node(cur); //node
		for (int i = s; i < e; i++) {
			if(cur==in[i]) {
				n.left=restore(s, i); //left child
				n.right=restore(i+1, e); //right child
			}
		}
		
		return n;
	}
	
	static void postorder (node n) {
		if(n.left!=null)postorder(n.left);
		if(n.right!=null)postorder(n.right);
		sb.append(n.num).append(" ");
	}
	
	static int pint(String s) {
		return Integer.parseInt(s);
	}
}

결과 화면

[문제링크]

 

20056번: 마법사 상어와 파이어볼

첫째 줄에 N, M, K가 주어진다. 둘째 줄부터 M개의 줄에 파이어볼의 정보가 한 줄에 하나씩 주어진다. 파이어볼의 정보는 다섯 정수 ri, ci, mi, si, di로 이루어져 있다. 서로 다른 두 파이어볼의 위치

www.acmicpc.net

 

0. 빠트린 부분 없이 잘 구현하면 되는 구현문제 (불가능)

 

1. 파이어볼 질량은 겹친 파이어볼이 분리될때에만 변경된다

  • 초기 질량합을 구해서 유지, 파이어볼 분리 작업마다 질량합을 수정한다

 

2. Fireball은 위치 + 질량/방향/속도 값을 가지며, 끊임없이 움직인다

  • 배열 : 여러 fireball을 저장하기 힘들다
  • List : fireball을 제거/이동하기 힘들다
  • Stack : push/pop으로 쉽게 이용 가능
  • 이런 이유로 Stack 사용

 

3. Stack을 가지는 class를 만들어 2차원 배열로 구현, Fireball의 위치 값을 표현했다

 

4. 이동 이후 Stack의 size가 1보다 크면 분리 작업 수행

 

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

public class Main{
	static class Fireball{
		Stack<int[]>balls;
		public Fireball() {
			balls= new Stack<>();
		}
	}
	static int[][] dir= new int[][] {
		{-1,0},{-1,1},{0,1},{1,1},{1,0},{1,-1},{0,-1},{-1,-1}
	};
	
	public static void main(String[] args)throws Exception {
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		
		StringTokenizer st = new StringTokenizer(br.readLine(), " ");
		int N = pint(st.nextToken());
		int M = pint(st.nextToken());
		int K = pint(st.nextToken());
		int totalW=0;
		
		Fireball[][] fireballs = new Fireball[N][N];
		for (int i = 0; i < N; i++) {
			for (int j = 0; j < N; j++) {
				fireballs[i][j]=new Fireball();
			}
		}
		
		for (int i = 0; i < M; i++) {
			int w;
			st = new StringTokenizer(br.readLine(), " ");
			fireballs[pint(st.nextToken())-1][pint(st.nextToken())-1]
					.balls.add(new int[] {w=pint(st.nextToken()),pint(st.nextToken()),pint(st.nextToken())});
			totalW+=w;
		}
		
		for (int i = 0; i < K; i++) {
			List<int[]> l = new ArrayList<>();
			//이동 시작
			for (int j = 0; j < N; j++) {
				for (int j2 = 0; j2 < N; j2++) {
					while(!fireballs[j][j2].balls.isEmpty()) {
						int[] ball = fireballs[j][j2].balls.pop();
						int x = j + dir[ball[2]][0]*ball[1]+N;
						int y = j2+ dir[ball[2]][1]*ball[1]+N;
						x%=N; if(x<0)x+=N;
						y%=N; if(y<0)y+=N;
						l.add(new int[] {x,y,ball[0],ball[1],ball[2]});
					}
				}
			}
			for (int[] b : l) {
				fireballs[b[0]][b[1]].balls.add(new int[] {b[2],b[3],b[4]});
			}
			
			//이동 끝
			for (int j = 0; j < N; j++) {
				for (int j2 = 0; j2 < N; j2++) {
					int size=0;
					if( (size = fireballs[j][j2].balls.size()) >1) {
						boolean same = true;
						int[] ball=fireballs[j][j2].balls.pop();
						int ballW = ball[0];//m,s,d
						int ballS = ball[1];
						int fstDir = ball[2]%2;
						int newDir=0;
						
						for (int o = 1; o < size; o++) {
							ball=fireballs[j][j2].balls.pop();
							ballW += ball[0];//m,s,d
							ballS += ball[1];
							if(fstDir != ball[2]%2)same=false;
						}
						totalW-=ballW;
						ballW/=5;
						ballS/=size;
						totalW+=ballW*4;
						
						if(ballW==0)continue;//0이면 소멸
						if(!same)newDir=1;
						for (int o = 0; o < 4; o++) {
							fireballs[j][j2].balls.add(new int[] {ballW, ballS, newDir});
							newDir+=2;
						}
					}
				}
			}//겹친 파이어볼 분리 끝
			
		}//K번 실행 끝
		System.out.println(totalW);
	}
	
	static int pint(String s) {
		return Integer.parseInt(s);
	}
}

결과 화면

'알고리즘 문제 풀이 > BOJ 골드' 카테고리의 다른 글

[백준] 14891 - 톱니바퀴  (0) 2021.09.27
[백준] 16919 - 봄버맨 2  (0) 2021.09.25
[백준] 4256 - 트리  (0) 2021.09.25
[백준] 6198 - 옥상 정원 꾸미기  (0) 2021.08.27
[백준] 2075 - N번째 큰 수  (0) 2021.08.27
[백준] 3190 - 뱀  (0) 2021.08.08
[백준] 14719 - 빗물  (0) 2021.08.08

[문제링크]

 

6198번: 옥상 정원 꾸미기

문제 도시에는 N개의 빌딩이 있다. 빌딩 관리인들은 매우 성실 하기 때문에, 다른 빌딩의 옥상 정원을 벤치마킹 하고 싶어한다. i번째 빌딩의 키가 hi이고, 모든 빌딩은 일렬로 서 있고 오른쪽으

www.acmicpc.net

 

0. 관리인은 오른쪽의, 자기보다 낮은 건물만 볼 수 있다

 

1. 빌딩들이 스택에 들어있을 때, 새로운 빌딩이 들어왔다면 2가지 경우가 된다

  • 이전 빌딩에서 관측 가능 : 이전 빌딩이 새 빌딩보다 높다
  • 이전 빌딩에서 관측 불가 : 이전 빌딩이 새 빌딩보다 낮다

 

2. 관측 가능한 빌딩을 만날때까지, 관측 불가능한 빌딩들은 다 스택에서 버린다

  • 스택에 [9,8,7,3,2,1] 이 있었다면, 5가 들어왔을때 3,2,1이 버려진다

 

3. 그 후 스택에 남아있는 빌딩들이 새 빌딩을 관측 가능한 빌딩들이다

  • 3,2,1을 버린 후 [9,8,7] 이 빌딩들은 5를 관측 가능하다

 

4. 스택의 크기만큼 관측 카운트를 누적시킨 후 새 빌딩 높이를 스택에 넣는다

 

※ 건물의 갯수는 최대 8만이므로, 최대 가능한 관측 수는 1+2+.... +79999+80000이다

  • 이는 (80000*80001)/2 = 대략 32억이므로, int 범위를 초과하니 long이나 uint 변수를 사용해야한다
  • JAVA에는 uint가 마땅히 없으므로 long을 사용
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.Stack;

public class Main{
	public static void main(String[] args)throws Exception {
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		
		int N = pint(br.readLine());
		long cnt=0;
		Stack<Integer> stack = new Stack<>();
		
		for (int i = 0; i < N; i++) {
			int h = pint(br.readLine());
			while(!stack.isEmpty() && stack.peek()<=h)stack.pop();
			cnt+=stack.size();
			stack.add(h);
		}
		System.out.println(cnt);
	}
	
	static int pint(String s) {
		return Integer.parseInt(s);
	}
}

결과 화면

'알고리즘 문제 풀이 > BOJ 골드' 카테고리의 다른 글

[백준] 16919 - 봄버맨 2  (0) 2021.09.25
[백준] 4256 - 트리  (0) 2021.09.25
[백준] 20056 - 마법사 상어와 파이어볼  (0) 2021.09.07
[백준] 2075 - N번째 큰 수  (0) 2021.08.27
[백준] 3190 - 뱀  (0) 2021.08.08
[백준] 14719 - 빗물  (0) 2021.08.08
[백준] 11062 - 카드게임  (0) 2021.07.31

[문제링크]

 

2075번: N번째 큰 수

첫째 줄에 N(1 ≤ N ≤ 1,500)이 주어진다. 다음 N개의 줄에는 각 줄마다 N개의 수가 주어진다. 표에 적힌 수는 -10억보다 크거나 같고, 10억보다 작거나 같은 정수이다.

www.acmicpc.net

 

0. 같은 열에서, 아래에 있는 값은 항상 윗 값보다 크다 = 해당 열의 최댓값은 가장 아래있는 값이다

 

1. 각 열마다 최댓값을 구해서 저장하고, 그중 가장 큰 값부터 하나씩 제외한다

  • 쉽고 효율적으로 최댓값을 구하기 위해 우선순위 큐 사용

 

2. 최댓값을 제외할 때 같은 열의 그다음 큰 값, 즉 바로 위의 값을 대신 저장한다

 

3. N번째 제외되는 최댓값이 곧 N번째로 큰 수이므로 구하려는 답이다

 

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.Comparator;
import java.util.PriorityQueue;
import java.util.StringTokenizer;

public class Main{
	public static void main(String[] args)throws Exception {
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));		
		
		int N = pint(br.readLine());
		int[][] num = new int[N][N];
		int[] idx = new int[N]; //각 열의 idx 관리
		int cnt=0;
		PriorityQueue<int[]> pq = new PriorityQueue<>(new Comparator<int[]>() {
			@Override
			public int compare(int[] o1, int[] o2) {
				// TODO Auto-generated method stub
				return o2[1]-o1[1];
			}
		});
		
		for (int i = 0; i < N; i++) {
			StringTokenizer st = new StringTokenizer(br.readLine());
			idx[i]=N-1;
			for (int j = 0; j < N; j++) num[i][j]=pint(st.nextToken());
		}
		
		for (int i = 0; i < N; i++) pq.add(new int[] {i, num[ idx[i]-- ][ i ]});
		
		while(cnt<N-1) {
			int[] cur = pq.poll();
			int i = cur[0];
			if(idx[i]>=0) { //더이상 값이 없을경우 처리
				int newV = num[ idx[i]-- ][i];
				pq.add(new int[] {i, newV});
			}
			
			cnt++;
		}
		System.out.println(pq.poll()[1]);
	}
	
	static int pint(String s) {
		return Integer.parseInt(s);
	}
}

결과 화면

'알고리즘 문제 풀이 > BOJ 골드' 카테고리의 다른 글

[백준] 4256 - 트리  (0) 2021.09.25
[백준] 20056 - 마법사 상어와 파이어볼  (0) 2021.09.07
[백준] 6198 - 옥상 정원 꾸미기  (0) 2021.08.27
[백준] 3190 - 뱀  (0) 2021.08.08
[백준] 14719 - 빗물  (0) 2021.08.08
[백준] 11062 - 카드게임  (0) 2021.07.31
[백준] 2600 - 구슬게임  (0) 2021.07.31

[문제링크]

 

3190번: 뱀

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

www.acmicpc.net

 

0. 스네이크 게임에서 생존 시간을 구하는 문제

 

1. 초기 방향은 항상 오른쪽이므로, 주어지는 방향 전환 데이터를 통해 몇초에, 어떤 방향으로 변하는지 미리 저장한다

 

2. 머리가 진행할 때, 해당 지점에 이동 방향 정보를 저장해 두어, 꼬리가 당겨질 때의 방향을 알 수 있도록 한다

 

3. 매 초 머리를 향하는 방향으로 이동하며,

  • 사과가 나온다면 - 길이를 1 늘린다, 즉 꼬리의 길이를 줄이지 않는다
  • 빈 공간이라면 - 꼬리를 이동시킨다
  • 벽이라면 - 종료한다

 

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

public class Main{
	
	static int[][] d={
		{0,0}, {0,-1}, {-1,0}, {0,1}, {1,0}
	};
	static int[][]map;
	static int[][]move;
	static int N;
	
	public static void main(String[] args)throws Exception {
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		
		N = pint(br.readLine());
		
		map=new int[N+2][N+2];
		for (int i = 0; i < N+2; i++) {
			map[0][i]=-1;
			map[N+1][i]=-1;
			map[i][0]=-1;
			map[i][N+1]=-1;
		}
		
		int k = pint(br.readLine());
		
		for (int i = 0; i < k; i++) {
			StringTokenizer st = new StringTokenizer(br.readLine(), " ");
			map[ pint(st.nextToken()) ][ pint(st.nextToken()) ]=5; // 사과 위치 표시
			
		}
		int L = pint(br.readLine());
		move = new int[L][2]; // 몇초에, 어떤 방향으로 바꿀지 저장
		int dir = 3; // 초기 방향
		for (int i = 0; i < L; i++) {
			StringTokenizer st = new StringTokenizer(br.readLine(), " ");
			move[i][0]=pint(st.nextToken());
			//현재 방향을 보고 다음 방향 계산
			switch (st.nextToken()) {
			case "D":
				dir++;
				if(dir==5)dir=1;
				move[i][1]=dir;
				break;
			case "L":
				dir--;
				if(dir==0)dir=4;
				move[i][1]=dir;
				break;
			default:
				break;
			}
		}
		
		int time=0; //생존 시간(구하려는 답)
		int cnt=0; // 회전 횟수
		dir=3;//초기방향
		int headX=1, headY=1;
		int tailX=1, tailY=1;
		while(true) {
			time++;
			//head이동
			map[headX][headY]=dir;
			headX+=d[dir][0];
			headY+=d[dir][1];

			if(map[headX][headY]==5) {//사과면 꼬리가 한칸 늘어나는효과 = 꼬리를 줄이지 않는다
			}
			else if(map[headX][headY]!=0) {//벽이면 죽음
				break;
			}
			else {//빈칸이면 꼬리를 한칸 당긴다
				int temp = map[tailX][tailY];
				map[tailX][tailY]=0;
				tailX+=d[temp][0];
				tailY+=d[temp][1];
			}
			
			//회전
			if(cnt<L && time == move[cnt][0]) {
				dir=move[cnt][1];
				cnt++;
			}
		}
		System.out.println(time);
	}
	
	static int pint(String s) {
		return Integer.parseInt(s);
	}
}

결과 화면

+ Recent posts