반응형

1. 언어 : JAVA

5427번: 불
 
www.acmicpc.net

 

 

2. 난이도 : Gold 4

 

3. 풀이

이 문제 역시 BFS이다.

 

아니 왜 그냥 골드4짜리에서 무작위로 고르는데 자꾸 BFS 문제가 나오는거지?

 

Anyway

 

이 문제는 BFS를 1개를 돌리면 되는 문제가 아니란걸 직감으로 느꼈다.

(사실 예전에 이런 비슷한 유형을 풀어본것 같기도?)

 

BFS문제는 설명하기가 힘든것 같다..

 

변수는 다음과 같다.

2차원 배열 check

2차원 배열 map

dequeSang // 상근이 큐

dequeFire // 불 큐

 

check는 상근이가 과거에 진입한 공간인지 아닌지 체크하는 곳

map은 벽과 불이 체크되어있는 곳.

 

BFS가 진행되면

1. Fire가 주위로 번지고(map에 표시)

2. 상근이가 있던곳 상하좌우 움직인다.

3-1. 만약 상근이가 움직이려고 하는 곳에 벽이나 Fire가 있으면 다음 단계 진행x

3-2. 만약 상근이가 움직이려고 하는 곳에 아무 장애물도 없으면 다음 단계 진행.

 

 

이렇게 하다보면 ,상근이가 벽쪽에 위치해 있을 때, 시간을 출력해주면된다.

 

설명보단 소스코드를 보면서 이해하는게 빠를 것같다.

 

혼자하면 이게문제야, 다른 코드도 보고싶은데 못봄.. 내가짠건 스파게티코드인데 흑흑 ㅜㅜ

 

 

4. 소스코드

import java.io.*;
import java.util.*;

class P {
	int y;
	int x;
	public P(int y, int x) {
		this.x = x;
		this.y = y;
	}
}
public class Main {
	public static int [] dx = {0, 0, -1, 1};
	public static int [] dy = {-1, 1, 0, 0};
	public static void main(String [] args) throws IOException {
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));
	
		int T = Integer.parseInt(br.readLine());
		String [][] map = null;
		int [][] check= null;
		Deque <P> dequeSang = null;
		Deque <P> dequeFire = null;
		int w = 0;
		int h = 0;
		
		for(int t=0; t<T; t++) {
			String [] temp = br.readLine().split(" ");
			w = Integer.parseInt(temp[0]);
			h = Integer.parseInt(temp[1]);
			map = new String[h][w];
			check = new int[h][w];
			dequeSang = new ArrayDeque<>();
			dequeFire = new ArrayDeque<>();
			
			int fireNum = 0;
			int sangNum = 0;
			
			for(int i=0; i<h; i++) {
				String s = br.readLine();
				for(int j=0; j<w; j++) {
					String st = s.substring(j, j+1);
					if(st.equals("@")) {
						check[i][j] = 1;
						sangNum ++;
						map[i][j] = ".";
						bw.flush();
						dequeSang.addLast(new P(i, j));
					}
					else if(st.equals("*")) {
						fireNum ++;
						dequeFire.addLast(new P(i, j));
						map[i][j] = st;
					}
					else {
						map[i][j] = st;
					}
				}
			}
			
			int fireNumTemp = 0;
			int sangNumTemp = 0;
			boolean find = false;
			int result = 0;
			int time = 0;
			
			while(!dequeFire.isEmpty() || !dequeSang.isEmpty()) {
				if(find) {
					break;
				}
				
				time ++;
				// fire Spread
				for(int i=0; i<fireNum; i++) {
					P pfire = dequeFire.pollFirst();
					int py = pfire.y;
					int px = pfire.x;
					for(int j=0; j<4; j++) {
						int ny = py + dy[j];
						int nx = px + dx[j];
												
						if(ny <= -1 || nx <= -1 || ny >= h || nx >= w) {
							continue;
						}
						
						if(map[ny][nx].equals("#") || map[ny][nx].equals("*")) {
							continue;
						}
						
						fireNumTemp ++;
						map[ny][nx] = "*";
						dequeFire.add(new P(ny, nx));
					}
				}
				fireNum = fireNumTemp;
				fireNumTemp = 0;
				
				for(int i=0; i<sangNum; i++) {
					P psang = dequeSang.pollFirst();
					int py = psang.y;
					int px = psang.x;
					
					for(int j=0; j<4; j++) {
						int ny = py + dy[j];
						int nx = px + dx[j];						
						
						if(ny <= -1 || nx <= -1 || ny >= h || nx >= w) {
							find = true;
							result = time;
							continue;
						}
						
						if(map[ny][nx].equals("*") || map[ny][nx].equals("#") || check[ny][nx] != 0) {
							continue;
						}

						sangNumTemp ++;
						check[ny][nx] = 1;
						dequeSang.addLast(new P(ny, nx));
					}
				}
				
				sangNum = sangNumTemp;
				sangNumTemp = 0;
			}
						
			if(result == 0)
				bw.write("IMPOSSIBLE\n");
			else
				bw.write(result + "\n");
			bw.flush();
		}
	}
}
반응형

'Algorithm > BFS' 카테고리의 다른 글

BOJ No.1261[알고스팟]  (0) 2021.03.12
BOJ No.12886[돌덩이]  (0) 2021.03.11
BOJ No.1005[AC Craft]  (0) 2021.03.11
반응형

1. 언어 : JAVA

1261번: 알고스팟
 
www.acmicpc.net

 
2. 난이도 : Gold 4

 

3. 풀이 

전형적인 BFS 문제이다. 

 

가장먼저

2차원 map

2차원 check(경로를 탐색 할 때의 메모이제이션 역할)

이 두가지면 충분하다.

 

2차원 배열 check 에는 이 배열까지 왔을 때, 몇개의 벽을 부셨을까이다.

 

즉,

 

4 4

0100

1000

0000

0000

 

이러한 입력이 주어졌다면,

(상우하좌 로 진행된다고 가정)

0111

1111

1111

1111

 

뭐 이런식으로 넣어질 것이다. 그래서!

다음 진행할 곳의 위치에서 벽을 사용한 값이 현재까지 벽 사용한 것의 + 1 보다 작거나 같으면 진행하지 않는다.

(이미 다른 녀석이 더 적은 벽을 뚫고 진행한 경험이 있기 때문에)

 
 
 
 

그리고 이렇게 벽이 있을때, 없을 때를 나눠서 queue에 넣어준다.

 

이렇게 진행하면 문제는 끝나게 된다.

 

하지만 이 문제를 해결하기 전에 처음에 메모리 초과 2번이나 났다.

왜냐하면, check 2차원 배열 안에 현재까지 깨뜨린 벽의 수를 넣은게 아니라 time기준으로 했기 때문이다.

아나 왜 time 기준으로했냐 똥멍청이냐

 

4. 소스코드

import java.util.*;
import java.io.*;

class p {
	int y;
	int x;
	int wall;
	public p(int y, int x, int wall) {
		this.y = y;
		this.x = x;
		this.wall = wall;
	}
}

public class Main {
	public static int [] dx = {0, 0, -1, 1};
	public static int [] dy = {-1, 1, 0, 0};
	public static BufferedReader br = null;
	public static BufferedWriter bw = null;
	public static void main(String [] args) throws IOException {
		int wallBreakNumber = 100001;
		br = new BufferedReader(new InputStreamReader(System.in));
		bw = new BufferedWriter(new OutputStreamWriter(System.out));
		Deque <p> deque = new ArrayDeque<>();
		
		StringTokenizer st = new StringTokenizer(br.readLine());
		
		int x = Integer.parseInt(st.nextToken());
		int y = Integer.parseInt(st.nextToken());
		
		int [][] map = new int[y][x];
		int [][] check = new int[y][x];
		
		for(int i=0; i<y; i++) {
			String s = br.readLine();
			for(int j=0; j<x; j++) {
				map[i][j] = Integer.parseInt(s.substring(j, j + 1));
				check[i][j] = 100001;
			}
		}
		
		// bfs
		check[0][0] = 0;
		deque.addLast(new p(0, 0, 0));
		while(!deque.isEmpty()) {
			p pair = deque.pollFirst();
			int px = pair.x;
			int py = pair.y;
			int pwall = pair.wall;
			
			if(py == y-1 && px == x-1) {
				wallBreakNumber = Math.min(pwall, wallBreakNumber);
			}
			
			for(int i=0; i<4; i++) {
				int nx = px + dx[i];
				int ny = py + dy[i];
								
				if(ny < 0 || ny >= y || nx < 0 || nx >= x) {
					continue;
				}
				
				if(check[ny][nx] <= pwall + 1) {
					continue;
				}
				
				if(map[ny][nx] == 1) {
					check[ny][nx] = pwall + 1;
					deque.addLast(new p(ny, nx, pwall + 1));
					continue;
				}
				
				if(map[ny][nx] == 0) {
					check[ny][nx] = pwall + 1;
					deque.addLast(new p(ny, nx, pwall));
					continue;
				}
			}
		}
		
		bw.write(wallBreakNumber + "\n");
		bw.flush();
		bw.close();
	}
}
반응형

'Algorithm > BFS' 카테고리의 다른 글

BOJ No.5427[불]  (0) 2021.03.14
BOJ No.12886[돌덩이]  (0) 2021.03.11
BOJ No.1005[AC Craft]  (0) 2021.03.11
반응형

1. 언어 : JAVA

12886번: 돌 그룹
 
www.acmicpc.net

2. 난이도 : Gold 5

 

3. 풀이

 

이 문제는 BFS 문제이다. 

그리고 3개의 돌이 주어지는데 메모이제이션으로 check[1501][1501][1501] 하면 메모리 초과가 난다.

그렇게이 첫번째, 두번째의 배열만 선언해줘도 충분하다.

(왜냐하면 처음, 두번째가 정해지면 3번째는 똑같이 오기 때문에)

 

그래서 check[1501][1501] 한개만 선언해줘도 충분하다.

 

그 다음은 문제에서 하라는대로하면된다.

 

1) 왼쪽 두개 비교 : 왼쪽이 더 클때

2) 왼쪽 두개 비교 : 오른쪽이 더 클때

3) 오른쪽 두개 비교 : 왼쪽이 더 클때

4) 오른쪽 두개 비교 : 오른쪽이 더 클때

(만약 이미 탐색한 경험이 있으면 진행하지 않는다.) 아래와 같이..

그리고 bfs함수 내에서 만약 모든 돌덩이가 같은 경우가 생기면 그 이후에 걸려있던 recursive는 다 제외 하도록함.

 

아마 메모리 초과와 처음에 어떤식으로 메모이제이션을 해야할지 감만 잡는다면 쉬운 문제인 것 같다.

 

 

 

4. 소스코드

import java.util.*;
import java.io.*;

public class Main {
	public static boolean b = false;
	public static BufferedReader br = null;
	public static BufferedWriter bw = null;
	public static boolean [][] check1 = null;
	public static boolean [][] check2 = null;
	public static void main(String [] args) throws IOException {
		br = new BufferedReader(new InputStreamReader(System.in));
		bw = new BufferedWriter(new OutputStreamWriter(System.out));

		int [] rocks = new int[3];
		check1 = new boolean[1501][1501];
		check2 = new boolean[1501][1501];
		String [] temp = br.readLine().split(" ");
		
		rocks[0] = Integer.parseInt(temp[0]);
		rocks[1] = Integer.parseInt(temp[1]);
		rocks[2] = Integer.parseInt(temp[2]);
		
		bfs(rocks);
		
		if(b == true) {
			bw.write("1" + "\n");
		}
		else {
			if(rocks[0] == rocks[1] && rocks[1] == rocks[2]) {
				bw.write("1" + "\n");
			}
			else {
				bw.write("0" + "\n");
			}
		}
		
		bw.flush();
		bw.close();
	}
	
	public static void bfs(int [] rocks) throws IOException {
		if(b == true) {
			return;
		}
		
		if(check1[rocks[0]][rocks[1]] && check2[rocks[0]][rocks[1]]) {
			if(rocks[0] == rocks[1] && rocks[0]== rocks[2]) {
				b = true;
			}
			return;
		}
				
		// 왼쪽 2개비교
		// 왼쪽이 더 클때
		if(rocks[0] > rocks[1]) {
			int previousLeft = rocks[0];
			int previousRight = rocks[1];
			rocks[0] = previousLeft - previousRight;
			rocks[1] = previousRight + previousRight;	
			if(!check1[rocks[0]][rocks[1]]) {
				check1[rocks[0]][rocks[1]] = true;
				bfs(rocks);
			}
			rocks[0] = previousLeft;
			rocks[1] = previousRight;
		}
		// 오른쪽이 더 클 때
		if(rocks[0] < rocks[1]) {
			int previousLeft = rocks[0];
			int previousRight = rocks[1];
			rocks[0] = previousLeft + previousLeft;
			rocks[1] = previousRight - previousLeft;
			if(!check1[rocks[0]][rocks[1]]) {
				check1[rocks[0]][rocks[1]] = true;
				bfs(rocks);
			}
			rocks[0] = previousLeft;
			rocks[1] = previousRight;
		}
		
		// 오른쪽 2개 비교
		// 왼쪽이 더 클때
		if(rocks[1] > rocks[2]) {
			int previousLeft = rocks[1];
			int previousRight = rocks[2];
			rocks[1] = previousLeft - previousRight;
			rocks[2] = previousRight + previousRight;	
			if(!check2[rocks[1]][rocks[2]]) {
				check2[rocks[1]][rocks[2]] = true;
				bfs(rocks);
			}
			rocks[1] = previousLeft;
			rocks[2] = previousRight;
		}
		// 오른쪽이 더 클 때
		if(rocks[1] < rocks[2]) {
			int previousLeft = rocks[1];
			int previousRight = rocks[2];
			rocks[1] = previousLeft + previousLeft;
			rocks[2] = previousRight - previousLeft;	
			if(!check2[rocks[1]][rocks[2]]) {
				check2[rocks[1]][rocks[2]] = true;
				bfs(rocks);
			}
			rocks[1] = previousLeft;
			rocks[2] = previousRight;
		}
	}
	
	public static int [] copyArray(int [] a) {
		int [] copyArray = new int[3];
		for(int i = 0; i < a.length; i ++) {
			copyArray[i] = a[i];
		}
		return copyArray;
	}
}
반응형

'Algorithm > BFS' 카테고리의 다른 글

BOJ No.5427[불]  (0) 2021.03.14
BOJ No.1261[알고스팟]  (0) 2021.03.12
BOJ No.1005[AC Craft]  (0) 2021.03.11
반응형
  1. 언어 : JAVA,

  2. 난이도 : Gold 3

  3. 문제 : 

    1005번: ACM Craft
     
    www.acmicpc.net
  1. 풀이

입력 :

5 10

100000 99999 99997 99994 99990

4 5

3 5

3 4

2 5

2 4

2 3

1 5

1 4

1 3

1 2

4

 

1) 반대서 오는 방법

2) 출발지를 정해주는 방법

 

밑에 소스코드는 2번을 사용했다.

그래프를 그려보면 다음과 같다.

처음에 1부터 시작해서

의 점화식으로 진행하려고 했다.

 

여기 까지는 맞았다고 생각한다. 근데 첫 위치를 어디서 시작해야하는지 감이 안왔다.

입력이 이상하게 들어오는(?) 

예를들어

2 1

3 4

1 3

이런식으로 들어오고 위에서부터 진행하면 2->1 3->4 1->3 ? 서로 연결이 되지 않는다.

따라서, 2->1 1->3 3->4 이런식으로 진행을 해줘야한다.

 

그래서 Node[N] 의 배열을 선언해주고,

다음 차례에 있는 Node의 값을 +1 시켜준다.

Node

[1] [2] [3] [4]

 1   0  1   1

 

이런식으로 저장이 되고,

0인 것만 처음에 시작을 해주면된다.

 

처음에 2에서 시작을해서,

진행을 하면서, 다음 노드를 들어가기 전에

-1 해주고 node[i] 가 0 일 때

큐에 다시 넣어주면

3부터 다시 시작해줄 수 있게된다.

 

이렇게 되면 BFS 비슷한 코드를 짤 수 있게 된다.

 

Node 배열을 사용하지 않으면 반대서 거꾸로 오는 방법도 있으니 참고했으면 좋겠다.

 

 

  1. 소스코드
import java.util.*;
import java.io.*;

public class baekjoon_1005 {
	public static BufferedReader br = null;
	public static BufferedWriter bw = null;
	public static ArrayList <Integer> [] map = null;
	public static void main(String [] args) throws IOException {
		br = new BufferedReader(new InputStreamReader(System.in));
		bw = new BufferedWriter(new OutputStreamWriter(System.out));

		int T = Integer.parseInt(br.readLine());
		
		for(int t = 0; t < T; t ++) {
			String [] temp = br.readLine().split(" ");
			int N = Integer.parseInt(temp[0]);
			int K = Integer.parseInt(temp[1]);
			
			int [] time = new int[N];
			int [] node = new int[N];
			int [] result = new int[N];
			
			temp = br.readLine().split(" ");
			ArrayList <Integer> [] map = new ArrayList[N];
			for(int j = 0; j < N; j ++) {
				time[j] = Integer.parseInt(temp[j]);
				map[j] = new ArrayList<>();
			}
			
			int s,e;
			for(int j = 0; j < K; j ++) {
				StringTokenizer st = new StringTokenizer(br.readLine());
				s = Integer.parseInt(st.nextToken());
				e = Integer.parseInt(st.nextToken());
				
				map[s-1].add(e - 1);
				node[e - 1] ++;
			}
			
            Queue<Integer> qu = new LinkedList<>();
            for(int i=0; i<N; i++) {
                if(node[i] == 0) {
                    result[i] = time[i];
                    qu.add(i);
                }
            }

            for(int i=0; i<N; i++) {
                int b = qu.poll();

                for(int index : map[b]) {
                    result[index] = Math.max(result[index], time[index] + result[b]);
                    if(--node[index] == 0){
                        qu.add(index);
                    }
                }
            }
			
			bw.write(result[Integer.parseInt(br.readLine())-1] + "\n");
		}
		bw.flush();
		bw.close();
	}
}
반응형

'Algorithm > BFS' 카테고리의 다른 글

BOJ No.5427[불]  (0) 2021.03.14
BOJ No.1261[알고스팟]  (0) 2021.03.12
BOJ No.12886[돌덩이]  (0) 2021.03.11

+ Recent posts