• 생각

1. 이 문제를 풀 때 가장 중요하게 알아야 하는 것은 정수 S와 K가 주어졌을 때, 합이 S인 K개의 양의 정수를 찾는 것이다. 어떻게 구할까??

합이 S인 K개의 양의 정수를 찾는 방법은 S를 K로 나눈 몫 K-1개나눈 몫+1 한개의 수인 K개의 수의 곱이 최대의 값을 가진다는 것이다.

 

  • 코드

정답 코드 : 합이 S인 K개의 양의 정수를 찾는 방법은 S를 K로 나눈 몫 K-1개 나눈 몫+1 한개의 수인 K개의 수의 곱이 최대의 값이다.

 

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

public class Main {
	static int S, K;

	public static void main(String[] args) throws Exception {
		SetData();
		System.out.println(FindMaxValue());
	}

	private static void SetData() throws Exception {
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		StringTokenizer st = new StringTokenizer(br.readLine());

		S = Integer.parseInt(st.nextToken());
		K = Integer.parseInt(st.nextToken());
	}

	private static long FindMaxValue() {
		int q = S / K; // 몫
		int r = S % K; // 나머지
		long max = 1;

		for (int i = 1; i <= K; i++) {
			if (i <= r) {// 나머지 갯수만큼 +1
				max *= (q + 1);
			} else {
				max *= q;
			}
		}

		return max;
	}
}

 


 

  • 생각

1. 점화식은 어떻게 생각해야될 지 감이 오지 않는다..

 

 

  • 코드

정답 코드 : 링크를 보고 이해하여서 코드를 작성했다. 다시 풀어봐야할 것 같음.

 

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

public class Algorithm {
	static int N, S;
	static int[] coin, dp;

	public static void main(String[] args) throws Exception {
		SetData();
		dp();
		System.out.println(dp[S]);
	}

	private static void SetData() throws Exception {
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		StringTokenizer st = new StringTokenizer(br.readLine());

		N = Integer.parseInt(st.nextToken());
		S = Integer.parseInt(st.nextToken());

		coin = new int[101]; 
		dp = new int[10001];

		for (int i = 1; i <= N; i++)
			coin[i] = Integer.parseInt(br.readLine());

		dp[0] = 1; 
	}

	private static void dp() {
		for (int i = 1; i <= N; i++) {
			for (int j = coin[i]; j <= S; j++) {
				dp[j] += dp[j - coin[i]];
			}
		}

	}
}

 


 

  • 생각

1. 배열 1개(윷놀이 판)로해서 만들어서 주사위 수에 따라서 굴리며 백트래킹하면 될 것 같다. ==>> 윷놀이를 하다가 10, 20, 30 (들어가는 부분) 때 잘 구해지지 않았다.

 

2. 배열을 2차원으로 만든다. (들어가는 곳별로 판을 새롭게 만듬) 배열의 값은 주사위 값 별로 해당되는 점수를 넣어줌. 이 배열을 주사위 수에따라 굴리며 백트래킹

 

 

  • 코드

정답 코드 : 맵을 4개를 만들어서 주사위 수에따라서 굴리며 백트래킹한다. 

 

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

public class Main {
	static int maxValue;
	static int[] dice, X, Y;
	static int[][] map;
	static boolean[][] check;

	public static void main(String[] args) throws Exception {
		SetData();
		dfs(0, 0);
		System.out.println(maxValue);
	}

	private static void SetData() throws Exception {
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		StringTokenizer st = new StringTokenizer(br.readLine());

		dice = new int[10];
		map = new int[4][30]; // 각 판의 점수를 저장
		check = new boolean[4][30]; // 해당 지역에 말이 있는지 없는지 check
		X = new int[4]; // 각각 주사위 위치 말 번호 저장
		Y = new int[4]; // 각각 주사위 맵 위치 저장
		maxValue = Integer.MIN_VALUE;

		for (int i = 0; i < 10; i++)
			dice[i] = Integer.parseInt(st.nextToken());

		map[0] = new int[] { 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, -1, -1, -1,
				-1, -1, -1, -1 };
		map[1] = new int[] { 0, 0, 0, 0, 0, 10, 13, 16, 19, 25, 30, 35, 40, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
				-1, -1, -1, -1 };
		map[2] = new int[] { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 20, 22, 24, 25, 30, 35, 40, -1, -1, -1, -1, -1, -1, -1, -1,
				-1, -1, -1 };
		map[3] = new int[] { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 30, 28, 27, 26, 25, 30, 35, 40, -1, -1, -1,
				-1, -1 };
	}

	private static void dfs(int index, int sum) {
		if (index == 10) {
			maxValue = Math.max(maxValue, sum);
			return;
		}
		for (int i = 0; i < 4; i++) {
			int tempX = X[i];
			int tempY = Y[i];

			if (map[X[i]][Y[i]] == -1)
				continue;
			check[X[i]][Y[i]] = false;

			//
			if (X[i] == 0) {
				switch (Y[i]) {
				case 5:
					X[i] += 1;
					break;
				case 10:
					X[i] += 2;
					break;
				case 15:
					X[i] += 3;
					break;
				}
			}

			Y[i] += dice[index];

			if (X[i] != 0) {
				// 바뀐 map의 주사위 위치에 따라 map을 바꿈
				switch (map[X[i]][Y[i]]) {
				case 40:
					X[i] = 0;
					Y[i] = 20;
					break;
				case 25:
					X[i] = 1;
					Y[i] = 9;
					break;
				case 30:
					X[i] = 1;
					Y[i] = 10;
					break;
				case 35:
					X[i] = 1;
					Y[i] = 11;
					break;
				}
			}

			if (!check[X[i]][Y[i]]) {
				if (map[X[i]][Y[i]] != -1) {
					check[X[i]][Y[i]] = true;
					dfs(index + 1, sum + map[X[i]][Y[i]]);
					check[X[i]][Y[i]] = false;
				} else {
					dfs(index + 1, sum);
				}
			}
			X[i] = tempX;
			Y[i] = tempY;
			check[X[i]][Y[i]] = true;
		}
	}
}

 

 

 

 


 

  • 생각

1. 어디서 많이 본 문제같다. 백준 1781번 : 컵라면 문제이다. 

 

  • 코드

정답 코드 : 배열에 값을 넣은 뒤 마감일로 오른차순 정렬을 한다. 그 후 우선순위 큐를 이용하여 풀었다.

 

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

public class Main {
	static int N;
	static int[][] array;

	public static void main(String[] args) throws Exception {
		SetData();
		System.out.println(FindMaxValue());
	}
	
	private static void SetData() throws Exception {
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		StringTokenizer st = null;
		
		N = Integer.parseInt(br.readLine());
		array = new int[N][2];
		
		for(int i = 0; i < N; i++) {
			st = new StringTokenizer(br.readLine());
			array[i][0] = Integer.parseInt(st.nextToken());
			array[i][1] = Integer.parseInt(st.nextToken());
		}
		
		// 2차원 배열 정렬 (deadline 오름차순)
		Arrays.sort(array, new Comparator<int[]>() {
		    @Override
		    public int compare(int[] o1, int[] o2) {
		        return o1[0] - o2[0];
		    }
		});
	}
	
	private static int FindMaxValue() {
        PriorityQueue<Integer> queue = new PriorityQueue<>();
        int sum = 0;
        for (int i = 0; i < N; i++) {
            queue.add(array[i][1]);
            while (!queue.isEmpty() && queue.size() > array[i][0]) queue.poll();
        }
        while (!queue.isEmpty())
            sum += queue.poll();
		return sum;
	}
}

 


 

  • 생각

 

1. 어떻게 풀어야할 지 1시간 생각해봤지만 감이 오지 않았다.... 이중 for문으로 구해봤지만 역시나 시간 초과.. 결국 검색을 했다...!

 

  • 코드

정답 코드 : 시작부터 끝까지의 부분합을 구하기 위해 (x2, y2)까지의 부분합을 더하고 (x1 - 1,  y2) (x2 , y1 - 1)을 빼줍니다. 그런데 이 때, 두 값을 뺀 부분의 교집합이 있으므로 해당 부분은 다시 더 해주는 방식을 사용했다.

 

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.LinkedList;
import java.util.Queue;
import java.util.StringTokenizer;
import java.util.regex.Pattern;

public class Algorithm {
	static int[][] array;
	static int[][] dp;

	public static void main(String[] args) throws Exception {
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		StringTokenizer st = new StringTokenizer(br.readLine());
		int N = Integer.parseInt(st.nextToken());
		int M = Integer.parseInt(st.nextToken());

		array = new int[N + 1][N + 1];
		dp = new int[N + 1][N + 1];

		for (int i = 1; i <= N; i++) {
			st = new StringTokenizer(br.readLine());
			for (int j = 1; j <= N; j++) {
				array[i][j] = Integer.parseInt(st.nextToken());
				dp[i][j] = dp[i][j - 1] + dp[i - 1][j] - dp[i - 1][j - 1] + array[i][j];
			}
		}

		StringBuilder sb = new StringBuilder();
		for (int i = 0; i < M; i++) {
			st = new StringTokenizer(br.readLine());
			sb.append(sum(Integer.parseInt(st.nextToken()), Integer.parseInt(st.nextToken()), 
					Integer.parseInt(st.nextToken()), Integer.parseInt(st.nextToken())) + "\n");
		}
		
		System.out.println(sb);
	}

	static int sum(int x1, int y1, int x2, int y2) {
		return dp[x2][y2] - dp[x2][y1 - 1] - dp[x1 - 1][y2] + dp[x1 - 1][y1 - 1];
	}
}

 


 

  • 생각

1. 코테보면 나올만한 문제인 것 같다. 다음과 같은 조건을 주의해서 코드를 짜면 될 것 같다.

 

조건 ) 1. <문자열>은 뒤집지 않고 출력 2. 문자열'띄어쓰기' or 문자열'문자열끝' 문자열 부분을 뒤집어서 출력

 

2. 스택을 잘 사용하면 시간이 더 빠르게 나올 것 같다.

 

3. StringTokenizer - 띄어쓰기된 문자열별로 .nextToken()으로 받아와서 작업해도 더 빠를 것 같다.

 

  • 코드

정답 코드 : 위의 조건들을 고려하여서 코드를 짰다.

 

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.LinkedList;
import java.util.Queue;
import java.util.StringTokenizer;
import java.util.regex.Pattern;

public class Main {

	public static void main(String[] args) throws Exception {
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		String s = br.readLine();
		String temp = "";
		StringBuilder sb = new StringBuilder();

		boolean check = false;
		for(int i = 0; i < s.length(); i++) {
			if(s.charAt(i) == '<')		// 뒤집지 않는 시작 문자 
				check = true;
			
			if(check)			// 뒤집지 않아야할 문자열
				temp = temp + s.charAt(i);
			else {				// 뒤집어야할 문자열
				if(s.charAt(i) == ' ')
					temp = temp + s.charAt(i);
				else
					temp = s.charAt(i) + temp;
			}
			
			if(s.charAt(i) == '>')		// 뒤집지 않는 끝 문자
				check = false;
			
			// ' ' or '>' or 문자열 끝이면 append
			if(s.charAt(i) == '>' || s.charAt(i) == ' ' || i == s.length()-1) {
				sb.append(temp);
				temp = "";
			}
			
		}
		System.out.println(sb);
	}
}

 

 

다른 사람 코드 : 스택으로 구현한 코드.

 

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.util.Stack;

public class Main {
    public static final char START_TAG = '<';
    public static final char END_TAG = '>';
    public static final char SPACE = ' ';

    public static void main(String args[]) {
        try (BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
                BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));) {
            String line = br.readLine();
            StringBuffer result = new StringBuffer();
            Stack<Character> word = new Stack<>();
            Boolean isTag = Boolean.FALSE;
            for (char c : line.toCharArray()) {
                if (c == START_TAG) {
                    if (!word.isEmpty()) {
                        result.append(reverse(word));
                    }
                    isTag = Boolean.TRUE;
                    result.append(c);
                } else if (c == END_TAG) {
                    result.append(c);
                    isTag = Boolean.FALSE;
                } else if (c == SPACE) {
                    if (isTag) {
                        result.append(c);
                    } else {
                        result.append(reverse(word));
                        result.append(SPACE);
                    }
                } else {
                    if (isTag) {
                        result.append(c);
                    } else {
                        word.add(c);
                    }
                }
            }
            if (!word.isEmpty()) {
                result.append(reverse(word));
            }
            bw.write(result.toString() + System.lineSeparator());

        } catch (IOException ioe) {
            ioe.printStackTrace();
        }
    }

    static String reverse(Stack<Character> input) {
        StringBuffer sb = new StringBuffer();
        while (!input.empty()) {
            sb.append(input.pop());
        }
        return sb.toString();
    }
}

 

다른 사람 코드 : StringTokenizer를 통해 구현한 코드가 있었다. 내가 생각했던 방식보다 더 활용을 잘한 코드이다. 제일 빨랐던 코드인만큼 공부하면 좋을 것 같다.

 

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

public class Main {
	static BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));

	static void solve(String target) {
		StringBuilder builder = new StringBuilder();
		StringTokenizer leftTagTokenizer = new StringTokenizer(target, "<");
		while (leftTagTokenizer.hasMoreTokens()) {
			String leftToken = leftTagTokenizer.nextToken();
			boolean includeTag = leftToken.contains(">");
			StringTokenizer rightTagTokenizer = new StringTokenizer(leftToken, ">");
			while (rightTagTokenizer.hasMoreTokens()) {
				if (includeTag) {
					builder.append("<");
					builder.append(rightTagTokenizer.nextToken());
					builder.append(">");
					includeTag = false;
				} else {
					String tagToken = rightTagTokenizer.nextToken();
					StringTokenizer spaceTokenizer = new StringTokenizer(tagToken);
					while (spaceTokenizer.hasMoreTokens()) {
						StringBuilder reverseBuilder = new StringBuilder(spaceTokenizer.nextToken());
						reverseBuilder.reverse();
						builder.append(reverseBuilder);
						if (spaceTokenizer.hasMoreTokens()) {
							builder.append(" ");
						}
					}
				}
			}
		}
		System.out.println(builder);
	}

	public static void main(String[] args) throws IOException {
		String line = reader.readLine();
		solve(line);
	}
}

 

 


 

  • 생각

1. queue를 두개를 만들어서 고슴도치가 움직이는 queue, 물이 차는 queue를 만들어서 bfs를 돈다. 이게 최선일 것 같은느낌..?

 

  • 코드

정답 코드 : 기본적인 BFS 문제인 것 같다. 중간에 코드를 잘 못 적어서 1시간 삽질했다..

 

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

public class Main {
	static int N, M, minValue, destinationX, destinationY;
	static Queue<int[]> HedgehogQueue, waterQueue;
	static char[][] array;
	static boolean[][] check;
	static int[] x = { -1, 1, 0, 0 };
	static int[] y = { 0, 0, -1, 1 };

	public static void main(String[] args) throws Exception {
		SetData();
		bfs();
		if (minValue == Integer.MAX_VALUE)
			System.out.println("KAKTUS");
		else
			System.out.println(minValue);
	}

	private static void SetData() throws Exception {
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		StringTokenizer st = new StringTokenizer(br.readLine());

		N = Integer.parseInt(st.nextToken());
		M = Integer.parseInt(st.nextToken());
		array = new char[N][M];
		check = new boolean[N][M];
		HedgehogQueue = new LinkedList<>();
		waterQueue = new LinkedList<>();
		minValue = Integer.MAX_VALUE;
		String s;

		for (int i = 0; i < N; i++) {
			s = br.readLine();
			for (int j = 0; j < M; j++) {
				array[i][j] = s.charAt(j);
				if (array[i][j] == 'D') {
					destinationX = i;
					destinationY = j;
				} else if (array[i][j] == 'S') {
					HedgehogQueue.offer(new int[] { i, j, 0 });
					check[i][j] = true;
				} else if (array[i][j] == '*') {
					waterQueue.offer(new int[] { i, j });
				}
			}
		}
	}

	private static void bfs() {
		while (!HedgehogQueue.isEmpty()) {
			int size = waterQueue.size();
			for (int i = 0; i < size; i++) {
				int location[] = waterQueue.poll();
				for (int direction = 0; direction < 4; direction++) {
					int r = location[0] + x[direction]; // 물 방향
					int c = location[1] + y[direction];

					if (r < 0 || r >= N || c < 0 || c >= M)
						continue;
					if (array[r][c] != '.')
						continue;
					array[r][c] = '*';
					waterQueue.offer(new int[] { r, c });
				}
			}

			size = HedgehogQueue.size();
			for (int i = 0; i < size; i++) {
				int location[] = HedgehogQueue.poll();
				int count = location[2];

				if (location[0] == destinationX && location[1] == destinationY) {
					minValue = Math.min(minValue, count); // 마지막 위치에 도달했을 때 지나온 칸 수를 return
				}

				for (int direction = 0; direction < 4; direction++) {
					int r = location[0] + x[direction]; // 고슴도치 방향
					int c = location[1] + y[direction];

					if (r < 0 || r >= N || c < 0 || c >= M)
						continue;
					if (check[r][c] || array[r][c] == '*' || array[r][c] == 'X')
						continue;
					check[r][c] = true;
					HedgehogQueue.offer(new int[] { r, c, count + 1 });
				}
			}
		}
	}
}

 


 

  • 생각

1. dfs로 푸는 방법 - 정확하게 풀 수 있다. 벽을 부수고 지나왔으면 그 다음 벽은 못 부수게 하면되고 안부수고 지나왔으면 다음 벽을 만났을 때 부술 수 있게 돌리면 된다. 최종으로 도달했을 때 가장 짧은 길이를 출력 ==>> 시간 초과

 

위의 사진은 어떤 분이 정리 해 둔 것인데 보면서 깨달으면 좋을 것 같아서 가져왔다.

 

  1. 가중치가 없는 최단 경로는 무조건 BFS입니다. 왜 DFS가 안 될까요? 그 이유는 당연하게도, 특정 칸에 처음 도달했을 때까지의 경로의 길이가 다른 경로를 통해 도달한 길이보다 짧다는 보장이 전혀 없기 때문입니다. 아직까지 이 사실을 모르고 계셨다면, 이 문제는 아직 풀기에 너무 어렵습니다. 더 기본적인 BFS 문제을 먼저 풀어보세요.
  2. 모든 칸을 전부 0으로 하나씩 바꾸어보고 BFS를 돌리는 것을 반복해서는 통과될 수 없습니다. 대부분의 알고리즘 문제가 그렇듯이, 풀이를 짜기 전에 반드시 해야 하는 것 중 하나는 시간 복잡도를 생각하는 것입니다. 시간 복잡도 계산, 전혀 어렵지 않습니다. 벽이 최대 O(NM)개 있는 맵에서, 벽을 하나 부술 때마다 O(NM)개의 칸을 탐색해야 하죠? 그러니 O((NM)^2)입니다. 이 수는 우리가 대충 1초에 돌 수 있다고 보는 단위인 1억을 10000배나 뛰어넘는 1조입니다. 절대 통과될 수 없겠죠?
  3. 칸마다 방문 체크 하나씩만 하는 방법으로는 풀 수 없습니다. 어떤 칸에 도달했을 때 나는 "아직 벽을 부술 수 있는 상태"일 수도 있고, "더 이상 벽을 부술 수 없는 상태"일 수도 있습니다. 큐에 그 상태를 넣은 것만으로 되는 것이 아닙니다. 당장 이 지점까지 어떻게든 최단으로 오는 길만 구했다고 해서, 그 이후의 여정도 최적으로 만들 수 있는 건 아닙니다. 구체적인 예시가 필요한가요?
    1. 현재 칸까지 벽을 안 부수고 최단으로 올 수 있었다고 가정해봅시다. 현재 지점에서 목표 지점까지 가는 데에, 벽을 한 개 부수고 가는 것이 안 부수고 가는 것보다 최적이 나온다고 해봅시다. 그렇다면 지금 내가 벽을 더 부술 수 있는 상태라는 사실을 알고 있어야만 되겠죠?
    2. 벽을 안 부수고도 현재 칸까지 도달이 가능하지만, 벽을 부수고 오는 것이 더 짧다고 가정해봅시다. 현재 지점에서 목표 지점까지 가려면 무조건 벽을 한 개 부숴야만 된다고 해봅시다. 비록 현재 칸까지는 벽을 부수고 오는 것이 최적이었지만, 이 상태로는 끝에 아예 도달을 못 하죠? 현재 칸까지는 더 멀더라도 벽을 안 부수고 와야, 끝에 도달이 가능하죠.
  4. (스포일러) 그래서 이 문제에서는 BFS에 대해 새로운 테크닉을 요구합니다. 단순히 좌표만을 큐에 넣어 탐색하는 방식을 넘어, "현재 상태" 자체를 큐에 넣어서 문제를 풀어야 합니다. 즉, 어떤 좌표에 있는가 뿐만 아니라, "여기까지 오면서 벽을 부순 적이 있는가" 여부를 함께 큐에 저장해서 탐색하고, 각각을 별개로 방문 체크해줘야 하는 문제입니다. visited[x][y]가 아니라, visited[x][y][벽을 부순 적이 있는가?] 가 되어야 합니다.
  5. 이 문제에서는 같은 칸에 방문하는 경우 벽을 안 부순 것이 더 유리하기 때문에 벽을 부쉈는지 여부를 방문 배열에 기록하여 부순 횟수가 더 적을 때만 방문하는 방법도 됩니다. 그러나 이는 문제의 특성 때문에 이 문제에서만 통하는 그리디이므로 다른 문제에도 함부로 사용해서는 안 됩니다.

2. bfs로 푸는 방법 - 조건을 잘 설정하면 dfs보다 메모리는 더 쓰겠지만 속도는 빠를 것 같다. (시간과 메모리 제한 보고 알고리즘을 생각하는 정도의 수준까지 오면 좋을 것 같다. ==>> 공부를 열심히 해야할 듯.)

 

 

  • 코드

정답 코드 : bfs로 풀었다. 여기서 핵심은 중복제거를 check[N][M][2]로 벽을 지나오면서 왔는지 아닌지 중복체크를 해주는 방법을 사용해야지만 정확히 풀 수 있는 문제이다. 

 

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

public class Main {
	static int N, M, minValue;
	static int[][] array;
	static boolean[][][] check;
	static int[] x = { -1, 1, 0, 0 };
	static int[] y = { 0, 0, -1, 1 };

	public static void main(String[] args) throws Exception {
		SetData();
		bfs();
        if(minValue == Integer.MAX_VALUE)
            System.out.println(-1);
        else    
            System.out.println(minValue);
	}

	private static void SetData() throws Exception {
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		StringTokenizer st = new StringTokenizer(br.readLine());

		N = Integer.parseInt(st.nextToken());
		M = Integer.parseInt(st.nextToken());
		array = new int[N][M];
		check = new boolean[N][M][2];
		minValue = Integer.MAX_VALUE;
		String s;
		
		for (int i = 0; i < N; i++) {
			s = br.readLine();
			for (int j = 0; j < M; j++) {
				array[i][j] = s.charAt(j) - '0';
			}
		}
	}

	private static void bfs() {
		Queue<int[]> queue = new LinkedList<>();
		queue.offer(new int[] { 0, 0, 1, 0 });

		while (!queue.isEmpty()) {
			int location[] = queue.poll();
			
			int count = location[2];
			int breakWall = location[3];
			if (location[0] == N - 1 && location[1] == M - 1) {
				minValue = Math.min(minValue, count);		// 마지막 위치에 도달했을 때 지나온 칸 수를 return
			}

			for (int direction = 0; direction < 4; direction++) {
				int r = location[0] + x[direction];
				int c = location[1] + y[direction];

				if (r < 0 || r >= N || c < 0 || c >= M)
					continue;
				if (array[r][c] == 1 && breakWall == 1)	// 지나온 벽이 있고 다음 칸도 벽이면 진행 X
					continue;

				if (breakWall == 1) {
					if (!check[r][c][breakWall] && array[r][c] == 0) {
						check[r][c][breakWall] = true;
						queue.offer(new int[] { r, c, count + 1, breakWall});
					}
				} else { // 벽을 안부순 상태
					if (!check[r][c][breakWall] && array[r][c] == 1) {
						check[r][c][breakWall] = true;
						queue.offer(new int[] { r, c, count + 1, breakWall + 1 });
					} else if (!check[r][c][breakWall] && array[r][c] == 0) {
						check[r][c][breakWall] = true;
						queue.offer(new int[] { r, c, count + 1, breakWall });
					}
				}
			}
		}
	}
}

+ Recent posts