728x90

문제

지훈이가 불에 타기 전에 미로를 탈출할 수 있으면

탈출 시간을 출력하고 불가능하다면 IMPOSSIBE을 출력하는 문제로

불은 매시간 상하좌우 4방향으로 한 칸씩 확산되고

지훈이는 상하좌우 한 칸씩 이동할 수 있다.

 

(지훈이와 불은 모두 벽을 통과할 수는 없다)

 

접근 방식

지훈이와 불을 동시에 출발시켜서 지훈이가 미로를 탈출하는지를

확인하면 되는 문제로 접근 방식을 떠올리는 건 간단한 문제다.

 

이제 어떻게 동시에 출발 시키냐는건데

일단 반복문에서 동시에 불과 지훈이를 한 번에

같이 탐색하는 건 불가능하다. (추후에 백트래킹을 배우면 가능하다.)

 

그래서 불과 지훈이를 각각 따로 움직여서 기록을 남길 건데,

이전에 풀어왔던 BFS 문제들처럼 거리를 남겨주면 된다.

 

불들의 거리를 모두 남긴 이후에 지훈이를 출발시켜서

불보다 짧으면 갈 수 있게 만들면 된다.

 

그리고 미로를 탈출한다는 것은 지훈이의 좌표가

배열의 범위를 벗어났다는 것을 확인해 주면 된다.

 

문제의 접근 자체는 쉬웠지만 풀이가 오래 걸렸던 문제인데

불이 하나가 아니라 여러 개라는 것을 조심해야 한다.

(이걸 몰라서 시간 잡아먹었다... 문제에 왜 안 적혀있는 건지...)

 

풀이

public class Main {

	private static int[] dx = {1, 0, -1, 0};
	private static int[] dy = {0, 1, 0, -1};

	public static void main(String[] args) throws IOException {
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		StringTokenizer st = new StringTokenizer(br.readLine(), " ");

		int r = Integer.parseInt(st.nextToken()); // n
		int c = Integer.parseInt(st.nextToken()); // m

		char[][] maze = new char[r][c];
		int[][] fireDistances = new int[r][c];
		int[][] jihunDistances = new int[r][c];

		Queue<Pair> fireQueue = new ArrayDeque<>();
		Queue<Pair> jihunQueue = new ArrayDeque<>();

		for (int i = 0; i < r; i++) {
			char[] input = br.readLine().toCharArray();

			for (int j = 0; j < c; j++) {
				maze[i][j] = input[j];

				jihunDistances[i][j] = -1;
				fireDistances[i][j] = -1;

				if (input[j] == 'J') {
					jihunDistances[i][j] = 0;
					jihunQueue.offer(new Pair(i, j));
				} else if (input[j] == 'F') {
					fireDistances[i][j] = 0;
					fireQueue.offer(new Pair(i, j));
				}
			}
		}

		while (!fireQueue.isEmpty()) {
			Pair cur = fireQueue.poll();

			for (int dir = 0; dir < 4; dir++) {
				int nx = cur.x + dx[dir];
				int ny = cur.y + dy[dir];

				if (nx < 0 || nx >= r || ny < 0 || ny >= c) continue;
				if (fireDistances[nx][ny] >= 0 || maze[nx][ny] == '#') continue;

				fireDistances[nx][ny] = fireDistances[cur.x][cur.y] + 1;
				fireQueue.offer(new Pair(nx, ny));
			}
		}

		while (!jihunQueue.isEmpty()) {
			Pair cur = jihunQueue.poll();

			for (int dir = 0; dir < 4; dir++) {
				int nx = cur.x + dx[dir];
				int ny = cur.y + dy[dir];

				if (nx < 0 || nx >= r || ny < 0 || ny >= c) {
					System.out.println(jihunDistances[cur.x][cur.y] + 1);
					return;
				}
				if (jihunDistances[nx][ny] >= 0 || maze[nx][ny] == '#') continue;
				if (fireDistances[nx][ny] != -1 && jihunDistances[cur.x][cur.y] + 1 >= fireDistances[nx][ny]) continue;

				jihunDistances[nx][ny] = jihunDistances[cur.x][cur.y] + 1;
				jihunQueue.offer(new Pair(nx, ny));
			}
		}

		System.out.println("IMPOSSIBLE");
	}

	private static class Pair {
		int x;
		int y;

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

 

'Java > Algorithms' 카테고리의 다른 글

[백준] 1012번 : 유기농 배추  (0) 2023.10.11
[백준] 1697번 : 숨바꼭질  (0) 2023.10.11
[백준] 7576번 : 토마토  (2) 2023.10.10
[백준] 2178번 : 미로 탐색  (0) 2023.10.09
[BFS] 구현 및 팁  (1) 2023.10.09
728x90

문제

상자에 익은 토마토와 덜 익은 토마토, 빈 공간이 존재할 때

익은 토마토의 주변 한 칸 내에 있는 덜 익은 토마토들은

하루가 지날 때마다 영향을 받아 익는다.

 

이때 상자 안에 존재하는 모든 토마토가 익기 위해서는

최소 며칠이 걸리는지 출력하라. (모두 익을 수 없는 경우에는 -1)

 

접근 방식

익은 토마토가 여러 곳에 존재하는 경우에는 각각의 익은 토마토에서

매일 상하좌우 칸의 덜 익은 토마토를 1로 바꿔줘야 한다.

 

이전에 풀었던 최단 거리 문제와 비슷한 방식으로 풀 수 있는 문제지만

출발지가 여러 개라는 조건이 추가된 문제다.

 

1926번 + 2176번 문제가 합쳐진 경우로

모든 출발지를 찾은 후에 큐에 넣고 BFS 알고리즘을 적용하면서

상하좌우에 거리를 1씩 늘려주면 된다.

 

이번 문제에서 거리는 날짜라고 볼 수 있다는 것이 포인트로

모든 열매가 다 익었을 때의 날짜를 출력하거나

큐를 다 돌았는데도 익지 않은 열매가 존재한다면 -1을 출력하면 된다.

 

풀이

public class Main {

	private static int[] dx = {1, 0, -1, 0};
	private static int[] dy = {0, 1, 0, -1};

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

		st = new StringTokenizer(br.readLine(), " ");

		int m = Integer.parseInt(st.nextToken());
		int n = Integer.parseInt(st.nextToken());

		int[][] tomato = new int[n][m];

		Queue<Pair> queue = new ArrayDeque<>();
		int[][] day = new int[n][m];

		int target = 0;

		for (int i = 0; i < n; i++) {
			st = new StringTokenizer(br.readLine(), " ");
			for (int j = 0; j < m; j++) {
				int t = Integer.parseInt(st.nextToken());
				tomato[i][j] = t;
				if (t == 1) {
					queue.offer(new Pair(i, j));
					day[i][j] = 1;
				} else if (t == 0) {
					target++;
				}
			}
		}

		if (target == 0) {
			System.out.println(0);
			return;
		}

		while (!queue.isEmpty()) {
			Pair cur = queue.poll();

			for (int dir = 0; dir < 4; dir++) {
				int nx = cur.x + dx[dir];
				int ny = cur.y + dy[dir];

				if (nx < 0 || nx >= n || ny < 0 || ny >= m) continue;
				if (day[nx][ny] > 0 || tomato[nx][ny] == -1) continue;

				target--;
				if (target == 0) {
					System.out.println(day[cur.x][cur.y]);
					return;
				}
				day[nx][ny] = day[cur.x][cur.y] + 1;
				queue.offer(new Pair(nx, ny));
			}

		}

		System.out.println(-1);
	}

	private static class Pair {
		int x;
		int y;

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

 

'Java > Algorithms' 카테고리의 다른 글

[백준] 1697번 : 숨바꼭질  (0) 2023.10.11
[백준] 4179번 : 불!  (0) 2023.10.10
[백준] 2178번 : 미로 탐색  (0) 2023.10.09
[BFS] 구현 및 팁  (1) 2023.10.09
[백준] 1926번 : 그림  (1) 2023.10.09
728x90

문제

1 0 1 1 1 1
1 0 1 0 1 0
1 0 1 0 1 1
1 1 1 0 1 1

 

위와 같은 미로가 주어졌을 때 도착지까지 갈 수 있는

최단 경로를 구하는 문제

 

접근 방식

기존 BFS 알고리즘으로 문제를 풀 때는 방문 여부만 기록했다면

이제는 방문 여부와 출발지로부터의 거리도 기록해주면 된다.

 

1 0 9 10 11 12
2 0 8 0 12 0
3 0 7 0 13 14
4 5 6 0 14 15

 

도착지를 처음 방문 했을 때가 가장 빠른 최단 경로일테니

출발지에서 도착지까지의 거리를 출력해주면 된다.

 

조심해야 할건 같은 지점에서 갈 수 있는 경로의 거리는

서로 같아야 한다.

 

1 0 9 10 11 13
2 0 8 0 14 0
3 0 7 0 15 16
4 5 6 0 17 18

 

이런식으로 되면 잘못된 결과가 나오게 된다.

 

풀이

public class Main {
	static int[] dx = {1, 0, -1, 0};
	static int[] dy = {0, 1, 0, -1};

	public static void main(String[] args) throws IOException {
		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());

		int[][] maze = new int[n][m];
		boolean[][] isVisited = new boolean[n][m];

		for (int i = 0; i < n; i++) {
			String[] input = br.readLine().split("");

			for (int j = 0; j < m; j++) {
				maze[i][j] = Integer.parseInt(input[j]);
			}
		}

		Queue<Pair> queue = new ArrayDeque<>();

		isVisited[0][0] = true;
		queue.offer(new Pair(0, 0, 1));

		while (!queue.isEmpty()) {
			Pair cur = queue.poll();

			if (cur.x == n - 1 && cur.y == m - 1) {
				System.out.println(cur.distance);
				break;
			}

			for (int dir = 0; dir < 4; dir++) {
				int nx = cur.x + dx[dir];
				int ny = cur.y + dy[dir];

				if (nx < 0 || nx >= n || ny < 0 || ny >= m)
					continue;
				if (maze[nx][ny] == 0 || isVisited[nx][ny])
					continue;

				isVisited[nx][ny] = true;
				queue.offer(new Pair(nx, ny, cur.distance + 1));
			}
		}
	}

	private static class Pair {
		int x;
		int y;
		int distance;

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

 

'Java > Algorithms' 카테고리의 다른 글

[백준] 4179번 : 불!  (0) 2023.10.10
[백준] 7576번 : 토마토  (2) 2023.10.10
[BFS] 구현 및 팁  (1) 2023.10.09
[백준] 1926번 : 그림  (1) 2023.10.09
[백준] 2504번 : 괄호의 값  (1) 2023.10.08
728x90

알고리즘 설명

가장 간단하게 설명하면 출발지에서 가까운 곳부터 방문하는 알고리즘으로

주로 최단 경로를 구할 때 많이 사용된다.

 

static int[][] board = {
    {1, 1, 1, 0, 1, 0, 0, 0, 0, 0},
    {1, 0, 0, 0, 1, 0, 0, 0, 0, 0},
    {1, 1, 1, 0, 1, 0, 0, 0, 0, 0},
    {1, 1, 0, 0, 1, 0, 0, 0, 0, 0},
    {0, 1, 0, 0, 0, 0, 0, 0, 0, 0},
    {0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
    {0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
};

 

위와 같은 2차원 배열이 주어졌을 때, 현재 위치에서 자신의 상하좌우 칸을

큐에 넣어주어 가까운 순서대로 반복하며 탐색하는 방법을 사용한다.

 

이때 이미 방문했던 칸은 다시 방문하지 않기 위해

방문해주었다는 기록을 남겨주고

범위를 벗어난 경우와 해당하지 않는 경우도 탐색하지 않게 조심해야 한다.

 

구현

주어진 배열에서 끊기지 않고 이어질 때까지만 탐색하여

이어진 길이 몇 개인지 확인하고 싶은 경우를 생각해보자

 

 

눈으로 확인하면 당연히 10개인걸 알 수 있지만

BFS 알고리즘을 모르고 구현하려면 까다로운 문제다.

 

(0, 0) 위치를 기준으로 출발하였을 때,

0인 경우는 신경 쓸 필요가 없으니 1인 경우만 큐에 넣어주면서

가까운 순서대로 탐색을 해주면 된다.

 

static boolean[][] isVisited = new boolean[502][502];

 

이때 방문했던 칸은 다시 방문하지 않기 위해

방문 여부를 기록할 배열을 하나 선언해준다.

 

Queue<Pair> Q = new LinkedList<>();
isVisited[0][0] = true;
Q.offer(new Pair(0, 0));

 

시작점인 (0, 0)을 큐에 넣어주고, 방문했으니 방문여부를 true로 설정해준다.

 

private static class Pair {
    int x, y;

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

 

Pair 클래스는 x와 y 좌표를 기록하는 클래스다.

(2차원 배열을 사용해도 무방하다.)

 

while (!Q.isEmpty()) {
    Pair cur = Q.poll();
    
    for (int dir = 0; dir < 4; dir++) {
        int nx = cur.x + dx[dir];
        int ny = cur.y + dy[dir];
        
        if (nx < 0 || nx >= n || ny < 0 || ny >= m) continue;
        if (isVisited[nx][ny] || board[nx][ny] != 1) continue;
        
        isVisited[nx][ny] = true;
        Q.offer(new Pair(nx, ny));
    }
}

 

그 다음에는 큐가 비어있을 때까지 ( = 이어진 1이 더이상 없는 경우)

반복문을 돌아주면서 현재 위치의 상하좌우를 방문하며

1이 있는 경우만 큐에 넣어주고 방문여부를 true로 바꿔준다.

 

while문에서 처음 꺼낸 cur은 현재 위치가 되고

현재 위치의 좌표를 기준으로 for문을 4번 반복하여

각각 상하좌우를 탐색한다.

 

static int[] dx = {1, 0, -1, 0};
static int[] dy = {0, 1, 0, -1};

 

방향을 햇갈리지 않기 위해 이렇게 배열에 적어주는 것이 좋다.

dx[0], dy[0] 일 때는 x만 한칸 움직이고 y는 그대로니

현재 위치에서 오른쪽 칸을 탐색하고

나머지는 순서대로 아래, 왼쪽, 위를 탐색한다.

(탐색 순서는 상관 없다) 

 

전체 코드

public class BFS {
	static int[][] board = {
		{1, 1, 1, 0, 1, 0, 0, 0, 0, 0},
		{1, 0, 0, 0, 1, 0, 0, 0, 0, 0},
		{1, 1, 1, 0, 1, 0, 0, 0, 0, 0},
		{1, 1, 0, 0, 1, 0, 0, 0, 0, 0},
		{0, 1, 0, 0, 0, 0, 0, 0, 0, 0},
		{0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
		{0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
	};

	static boolean[][] isVisited = new boolean[502][502];
    
	static int n = 7, m = 10;
    
	static int[] dx = {1, 0, -1, 0};
	static int[] dy = {0, 1, 0, -1};

	public static void main(String[] args) {
		Queue<Pair> Q = new LinkedList<>();
		isVisited[0][0] = true;
		Q.offer(new Pair(0, 0));
        
		int count = 1;

		while (!Q.isEmpty()) {
			Pair cur = Q.poll();
            
			for (int dir = 0; dir < 4; dir++) {
				int nx = cur.x + dx[dir];
				int ny = cur.y + dy[dir];
                
				if (nx < 0 || nx >= n || ny < 0 || ny >= m) continue;
				if (isVisited[nx][ny] || board[nx][ny] != 1) continue;
                
				isVisited[nx][ny] = true;
				Q.offer(new Pair(nx, ny));
                count++;
			}
		}
        
        System.out.println(count);
	}

	private static class Pair {
		int x, y;

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

 

여러 개를 탐색하고 확인해야 하는 경우

 

위와 같이 길들이 총 몇 개 존재하고 길들의 길이는 몇인지 알고 싶은 경우에는

시작점이 몇 개인지 파악하고 각각의 시작점에서

그대로 while문을 통해 탐색을 해주면 된다.

 

2차원 배열을 이중 for문으로 돌아주면서

시작점이 될 수 있는 경우 BFS 알고리즘을 통해 탐색해주면 된다.

 

최단 거리를 구해야 하는 경우

1 0 1 1 1 1
1 0 1 0 1 0
1 0 1 0 1 1
1 1 1 0 1 1

위와 같은 2차원 배열이 주어졌을 때

(0, 0)에서 (4, 5)로 가는 최단 거리를 구해야 할 때는

기존에는 방문 여부를 기록했다면 출발지에서부터의

거리를 기록해주면서 방문 여부를 기록하면 된다.

'Java > Algorithms' 카테고리의 다른 글

[백준] 7576번 : 토마토  (2) 2023.10.10
[백준] 2178번 : 미로 탐색  (0) 2023.10.09
[백준] 1926번 : 그림  (1) 2023.10.09
[백준] 2504번 : 괄호의 값  (1) 2023.10.08
[백준] 10799번 : 쇠막대기  (0) 2023.10.07
728x90

문제

1 1 0 1 1
0 1 1 0 0
0 0 0 0 0
1 0 1 1 1
0 0 1 1 1
0 0 1 1 1

 

위와 같은 입력이 주어졌을 때

그림의 개수와 가장 큰 그림의 사이즈를 출력하는 문제

 

접근 방식

 

위의 입력에서는 총 4개의 그림이 있고

가장 큰 그림의 사이즈는 9라는 것을 알 수 있다.

 

눈으로 보면 당연한 거지만 이를 코드로 구현하는 것이

BFS를 처음 배우고 푸는 문제라서 많이 어려웠다...

 

우선 입력 받은 값들을 그림 배열에 저장해 준 후에

해당 그림 배열을 돌면서 찾아주면 된다.

 

이때 방문한 배열을 다시 방문하지 않기 위해

0이나 1 혹은 true false로 방문 여부를 저장할 배열을 만들어 기록해 준다.

 

Queue<Pair> Q = new LinkedList<>();
isVisited[0][0] = true;
Q.add(new Pair(0, 0));

while (!Q.isEmpty()) {
    Pair cur = Q.poll();
    System.out.print("(" + cur.x + ", " + cur.y + ") -> ");
    for (int dir = 0; dir < 4; dir++) {
        int nx = cur.x + dx[dir];
        int ny = cur.y + dy[dir];
        if (nx < 0 || nx >= n || ny < 0 || ny >= m) continue;
        if (isVisited[nx][ny] || board[nx][ny] != 1) continue;
        isVisited[nx][ny] = true;
        Q.add(new Pair(nx, ny));
    }
}

 

기본적인 BFS 알고리즘의 구조는 위와 같이

현재 위치에 상하좌우를 확인하는 방식이다.

 

코드를 보면 알 수 있듯이 이미 방문했거나 값이 1이 아닌 경우에는

방문하지 않고 넘어가는데 이 과정을 통해

1이 끊기지 않고 연결된 수를 알 수 있다.

 

즉, 그림 하나의 사이즈를 알 수 있는데

문제에서는 추가적으로 그림의 개수도 세어줘야 하기 때문에

그림의 시작점을 찾아서

해당 시작점마다 그림의 개수를 1씩 증가시키고

BFS 알고리즘을 적용하여 사이즈를 계산해 주면 된다.

 

풀이

public class Main {

	static int[] dx = {1, 0, -1, 0};
	static int[] dy = {0, 1, 0, -1};

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

		String[] nm = br.readLine().split(" ");
		int n = Integer.parseInt(nm[0]);
		int m = Integer.parseInt(nm[1]);

		int[][] painting = new int[n][m];

		for (int i = 0; i < n; i++) {
			String[] input = br.readLine().split(" ");

			for (int j = 0; j < m; j++) {
				painting[i][j] = Integer.parseInt(input[j]);
			}
		}

		boolean[][] isVisited = new boolean[502][502];

		int max = 0;
		int count = 0;

		for (int i = 0; i < n; i++) {
			for (int j = 0; j < m; j++) {
				if (painting[i][j] == 0 || isVisited[i][j]) continue;
				count++;
				Queue<Pair> queue = new ArrayDeque<>();

				isVisited[i][j] = true;
				queue.offer(new Pair(i, j));

				int area = 0;

				while (!queue.isEmpty()) {
					area++;
					Pair cur = queue.poll();

					for (int dir = 0; dir < 4; dir++) {
						int nx = cur.x + dx[dir];
						int ny = cur.y + dy[dir];

						if (nx < 0 || nx >= n || ny < 0 || ny >= m) continue;
						if (isVisited[nx][ny] || painting[nx][ny] != 1) continue;

						isVisited[nx][ny] = true;
						queue.offer(new Pair(nx, ny));
					}

					max = Math.max(max, area);
				}
			}
		}

		System.out.println(count + "\n" + max);
	}

	private static class Pair {
		int x, y;

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

 

'Java > Algorithms' 카테고리의 다른 글

[백준] 2178번 : 미로 탐색  (0) 2023.10.09
[BFS] 구현 및 팁  (1) 2023.10.09
[백준] 2504번 : 괄호의 값  (1) 2023.10.08
[백준] 10799번 : 쇠막대기  (0) 2023.10.07
[백준] 3986번 : 좋은 단어  (0) 2023.10.07
728x90

문제

() = 2, [] = 3 이고

(x) = 2 * x, [x] = 3 * x 일 때

괄호로만 이루어진 문자열의 계산 결과를 구하는 문제

 

(잘못된 괄호인 경우에는 무조건 0을 출력)

 

접근 방식

문제의 이해는 쉽지만 구현이 어려웠던 문제다.

(()[[]])([])

(
((
(()
(2
(2[
(2+[[
(2+[[]
(2+[3
(2+[3]
(2+9
(11
(11)
22
22+(
22+([
22+([]
22+(3
22+(3)
22+6
28

 

주어진 문자열에 대한 계산 순서는 위와 같은데

문제를 자세히 읽어 보면 잘못된 괄호의 경우에는 생각할 필요가 없고

제대로 된 괄호의 경우만 생각하면 된다.

 

즉, 모든 괄호가 알맞게 짝지어져 있다는 가정 하에 계산을 하면 되는데

() = 2니까 (()) = 2의 제곱, ((())) = 2의 3제곱이 되고,

[] = 3이니 [[]] = 3의 제곱, [[[]]] = 3의 3제곱이 된다.

 

소괄호가 들어오면 num에 2를 곱해주고 대괄호가 들어오면 3을 곱해준 다음에

괄호가 닫히면 더해주고 닫힌 괄호로 다시 나눠주면 된다.

 

풀이

public class Main {

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

		char[] input = br.readLine().toCharArray();

		Stack<Character> stack = new Stack<>();

		int sum = 0;
		int num = 1;

		for (int i = 0; i < input.length; i++) {
			char c = input[i];

			if (c == '(') {
				stack.push(c);
				num *= 2;
			} else if (c == '[') {
				stack.push(c);
				num *= 3;
			} else if (c == ')') {
				if (stack.isEmpty() || stack.peek() != '(') {
					System.out.println(0);
					return;
				}

				stack.pop();

				if (input[i - 1] == '(') {
					sum += num;
				}
				num /= 2;
			} else {
				if (stack.isEmpty() || stack.peek() != '[') {
					System.out.println(0);
					return;
				}

				stack.pop();

				if (input[i - 1] == '[') {
					sum += num;
				}
				num /= 3;
			}
		}

		if (stack.isEmpty()) {
			System.out.println(sum);
		} else {
			System.out.println(0);
		}
	}
}

 

'Java > Algorithms' 카테고리의 다른 글

[BFS] 구현 및 팁  (1) 2023.10.09
[백준] 1926번 : 그림  (1) 2023.10.09
[백준] 10799번 : 쇠막대기  (0) 2023.10.07
[백준] 3986번 : 좋은 단어  (0) 2023.10.07
[백준] 4949번 : 균형잡힌 세상  (0) 2023.10.05
728x90

문제

주어진 쇠막대기들에 레이저를 발사했을 때 쇠막대기가

총 몇 개로 나뉘는지 계산하는 문제

 

접근 방식

풀고 나니 엄청 간단했지만 풀이법을 알기까지 많은 시간이 걸린 문제로

코드를 보면 알겠지만 엄청 간단한 문제다.

 

()(((()())(())()))(())

위와 같은 문자열이 주어졌을 때

괄호가 열리자마자 닫히면 레이저고

그렇지 않다면 쇠막대기라는 것을 알 수 있다.

 

쇠막대기의 양끝과 레이저는 겹치지 않기 때문에

쇠막대기 위에 레이저가 발사되면 무조건 쇠막대기가 잘라진다.

 

즉 레이저를 쐈을 때 현재 스택에 있는 쇠막대기의 수만큼

쇠막대기가 늘어나기 때문에

열리자마자 닫히는 괄호를 발견했을 때마다

스택의 사이즈만큼 더해주면 된다.

 

주의해야 할 점은 쇠막대기가 끝날 때도 1씩 더해줘야 하는데

길이가 3인 쇠막대기를 2번 자르면 3개가 되기 때문이다.

 

이해가 어렵다면 아래 과정을 참고하길 바란다

 

()(((()())(())()))(())

레이저 +0
막대기 1
막대기 2
막대기 3
레이저 +3
레이저 +3
막대기 2 +1
막대기 3
레이저 +3
막대기 2 +1
레이저 +2
막대기 1 +1
막대기 0 +1
막대기 1
레이저 +1
막대기 0 +1 

총 17조각

 

 

풀이

public class Main {

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

		char[] input = br.readLine().toCharArray();

		Stack<Character> stack = new Stack<>();

		int count = 0;

		for (int i = 0; i < input.length; i++) {
			if (input[i] == '(') {
				stack.push(input[i]);
			} else if (input[i - 1] == '(' && input[i] == ')'){
				stack.pop();
				count += stack.size();
			} else {
				stack.pop();
				count++;
			}
		}

		System.out.println(count);
	}
}

 

'Java > Algorithms' 카테고리의 다른 글

[백준] 1926번 : 그림  (1) 2023.10.09
[백준] 2504번 : 괄호의 값  (1) 2023.10.08
[백준] 3986번 : 좋은 단어  (0) 2023.10.07
[백준] 4949번 : 균형잡힌 세상  (0) 2023.10.05
[백준] 5430번 : AC  (1) 2023.10.04
728x90

문제

A와 B로만 이루어진 문자열이 주어졌을 때

같은 글자끼리 선을 그어 교차하지 않고 모두 맞아떨어지는 경우

주어진 문자열을 좋은 단어라고 판단하고

좋은 단어가 몇개인지 출력하는 문제

 

접근 방식

좋은 단어에 대한 설명이 헷갈릴 수 있는데 아래와 같다.

 

AABB (O)

ABBA (O)

ABAB (X)

 

알 수 있는 사실은 연속해서 존재하거나 중간에 다른 단어의 선과 겹치면 안 된다는 건데

같은 경우 빼주고 같지 않은 경우는 넣어주면 되므로 스택을 사용하면 쉽게 풀 수 있다.

 

ABBA 같은 경우만 신경 써서 풀면 되는 문제로

아래와 같은 순서로 실행되는 코드를 짜면 된다.

 

Stack<Character> stack = new Stack<>();

// ABBA

stack.push('A');	// stack(A)
peek() == 'B';	// 'A' == 'B'
stack.push('B');	// stack(A, B)
peek() == 'B';	// 'B' == 'B'
stack.pop();	// stack(A)
peek() == 'A';	// 'A' == 'A'
stack.pop();	// stack()

 

위와 같은 과정을 거치면 좋은 단어인 경우에는

스택에 아무런 값도 남지 않기 때문에

스택이 비었을 때 좋은 단어의 카운트를 1씩 증가시켜 주면 된다.

 

 

풀이

public class Main {

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

		int n = Integer.parseInt(br.readLine());

		int result = 0;

		for (int i = 0; i < n; i++) {
			char[] word = br.readLine().toCharArray();

			Stack<Character> stack = new Stack<>();

			for (char c : word) {
				if (stack.isEmpty()) {
					stack.push(c);
				} else {
					char top = stack.peek();
					if (top == c){
						stack.pop();
					} else {
						stack.push(c);
					}
				}
			}

			if (stack.isEmpty()) {
				result++;
			}
		}

		System.out.println(result);
	}
}

 

'Java > Algorithms' 카테고리의 다른 글

[백준] 2504번 : 괄호의 값  (1) 2023.10.08
[백준] 10799번 : 쇠막대기  (0) 2023.10.07
[백준] 4949번 : 균형잡힌 세상  (0) 2023.10.05
[백준] 5430번 : AC  (1) 2023.10.04
[백준] 1021번 : 회전하는 큐  (0) 2023.10.04

+ Recent posts