Notice
Recent Posts
Recent Comments
Link
«   2024/05   »
1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31
Archives
Today
Total
관리 메뉴

최's 먹공로그

BOJ18809 Gaaaaaaarden 본문

APS

BOJ18809 Gaaaaaaarden

ChoiSH313 2022. 10. 8. 13:52

<문제 요약>

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

 

18809번: Gaaaaaaaaaarden

첫째 줄에 정원의 행의 개수와 열의 개수를 나타내는 N(2 ≤ N ≤ 50)과 M(2 ≤ M ≤ 50), 그리고 초록색 배양액의 개수 G(1 ≤ G ≤ 5)와 빨간색 배양액의 개수 R(1 ≤ R ≤ 5)이 한 칸의 빈칸을 사이에 두

www.acmicpc.net

1. 배양액은 매 초마다 이전에 배양액이 도달한 적이 없는 인접한 땅으로 퍼져간다
2. 초록색 배양액과 빨간색 배양액이 동일한 시간에 도달한 땅에서는 꽃 -> 꽃이 핀 곳에서는 배양액이 퍼지지 않는다
3. 배양액을 남김없이 사용해야 한다
4. 꽃의 최대 개수를 구하자
5. 입력
N, M, G, R 행, 열, 초록색 배양액, 빨간색 배양액
0, 1, 2 호수, 배양액을 뿌릴 수 없는 땅, 배양액을 뿌릴 수 있는 땅

<풀이 흐름, Source Code>

1. 변수 선언
(1) x,y,color,time 을 변수로 갖는 구조체 선언 pair
(2) pair형의 map 선언
(3) pair형의 list 선언 position
(4) total_time

2. 풀이
(1) map 중 2로 입력되는 곳의 x,y,color,time을 list position에 따로 저장해둔다
(2) list position에서 배양액이 위치할 수 있는 경우를 조합을 통해 다 뽑아낸다
배열 pick에는 3 빈곳, 4 green, 5 red로 표현하고
배양액이 위치할 수있는 곳이 총 5군데이고 green 2, red 1이라고 한다면 아래와 같이 데이터가 나와야 된다
2 2 1 0 0 0
2 2 0 1 0 0
2 2 0 0 1 0
.......
0 0 0 1 2 2
그러면 list position에 위치가 5군데 있을 것이고 0 0 0 1 2 2의 경우 첫번째~세번째까지는 빈곳 네번째 green 5~6번째 red를 위치
한다.

(3) bfs를 돌린다
(3)-1. 호수인 곳은 갈 수 없다 map.color = 0
(3)-2. 꽃인 곳은 갈 수 없다 map.color = 6
(3)-3. 동시간대가 아닌 배양액이 위치한 곳은 갈 수 없다 map.color = 4 or 5 & map.time != total_time
(3)-4. 배열을 벗어나는 곳은 갈수없다
※ map.color가 position.color와 서로 반대되는 배양액이고 동시간대이면 꽃으로 변한다!!

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.Queue;
import java.util.StringTokenizer;

public class BOJ18809_Gaaaaaaarden {

	private static class pair {
		int x, y, color, time;

		pair(int x, int y, int color, int time) {
			this.x = x;
			this.y = y;
			this.color = color;
			this.time = time;
		}
	}

	static final int EMPTY = 0, RED = 4, GREEN = 5, FLOWER = 6;
	static pair map[][];
	static pair map_copy[][];
	static boolean visited[][];
	static int pick[];
	static int N, M, G, R, total_time, result = -1;
	static ArrayList<pair> position;
	static Queue<pair> q = new LinkedList<>();
	static int[] dx = { 0, 1, 0, -1 }, dy = { -1, 0, 1, 0 };

	public static void main(String[] args) throws IOException {
		input();
		pick = new int[position.size()];
		combination(pick, R, G, 0);
		System.out.print(result);
	}

	private static void input() throws IOException {
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		StringTokenizer st = new StringTokenizer(br.readLine(), " ");
		N = Integer.parseInt(st.nextToken());
		M = Integer.parseInt(st.nextToken());
		G = Integer.parseInt(st.nextToken());
		R = Integer.parseInt(st.nextToken());
		map = new pair[N][M];
		map_copy = new pair[N][M];
		visited = new boolean[N][M];
		for (int i = 0; i < N; i++) {
			for (int j = 0; j < M; j++) {
				map[i][j] = new pair(0, 0, 0, 0);
				map_copy[i][j] = new pair(0, 0, 0, 0);
			}
		}
		position = new ArrayList<pair>();
		total_time = 0;
		for (int i = 0; i < N; i++) {
			st = new StringTokenizer(br.readLine(), " ");
			for (int j = 0; j < M; j++) {
				int what = Integer.parseInt(st.nextToken());
				map[i][j].color = what;
				map[i][j].time = 0;
				map_copy[i][j].color = what;
				map_copy[i][j].time = 0;
				if (what == 2) {
					position.add(new pair(i, j, what, 0));
				}
			}
		}
	}

	private static int bfs() {
		int bfs_result = 0;
		for (int i = 0; i < position.size(); i++) {
			if (pick[i] != EMPTY) {
				pair p = position.get(i);
				q.add(new pair(p.x, p.y, pick[i], total_time));
				map[p.x][p.y].color = pick[i];
				visited[p.x][p.y] = true;
			}
		}

		while (!q.isEmpty()) {
			int q_size = q.size();
			total_time++;
			for (int size = 0; size < q_size; size++) {
				pair p = q.poll();
				// 현재칸 체크
				if(map[p.x][p.y].color == FLOWER || map[p.x][p.y].color == 0)
					continue;
				for (int di = 0; di < 4; di++) {
					int nx = p.x + dx[di];
					int ny = p.y + dy[di];
					if (nx >= 0 && nx < N && ny >= 0 && ny < M) {
						if (map[nx][ny].color == 0 || map[nx][ny].color == FLOWER)
							continue;
						else if ((map[nx][ny].color == GREEN || map[nx][ny].color == RED)
								&& map[nx][ny].time != total_time) {
							continue;
						} else if (!visited[nx][ny] && (map[nx][ny].color == 1 || map[nx][ny].color == 2)) {
							visited[nx][ny] = true;
							map[nx][ny].color = p.color;
							map[nx][ny].time = total_time;
							q.add(new pair(nx, ny, p.color, total_time));
						} else if (map[nx][ny].color == RED && map[nx][ny].time == total_time) {
							if (p.color == GREEN) {
								map[nx][ny].color = FLOWER;
								bfs_result++;
							}
						} else if (map[nx][ny].color == GREEN && map[nx][ny].time == total_time) {
							if (p.color == RED) {
								map[nx][ny].color = FLOWER;
								bfs_result++;
							}
						}
					}
				}
			}
		}

		return bfs_result;
	}

	static void combination(int[] pick, int red, int green, int start) {
		if (red == 0 && green == 0) {
			result = Math.max(bfs(), result);
			for(int i = 0; i < N; i++) {
				for(int j = 0; j < M; j++) {
					map[i][j].color = map_copy[i][j].color;
					map[i][j].time = map_copy[i][j].time;
					visited[i][j] = false;
				}
			}
			return;
		}

		for (int i = start; i < pick.length; i++) {
			if (pick[i] == EMPTY) {
				if (red > 0) {
					pick[i] = RED;
					combination(pick, red - 1, green, Math.max(start, i + 1));
					pick[i] = EMPTY;
				}
			}
		}

		for (int i = start; i < pick.length; i++) {
			if (pick[i] == EMPTY) {
				if (green > 0) {
					pick[i] = GREEN;
					combination(pick, red, green - 1, Math.max(start, i + 1));
					pick[i] = EMPTY;
				}
			}
		}
	}
}

 

<문제 Issue>

1. 인접한 칸을 검사하기 전에 현재 칸도 검사해야 된다. 동시간대에 두개의 배양액이 합쳐진 곳은 꽃으로 변하는데 꽃으로 변하기 전 배양액은 이미 큐에 들어간 상태라서 다음에 꺼내서 또 인접한 곳으로 퍼트린다.

0초

     
G   R

1초 G

G    
G G R

이때 두개의 G는 큐에 들어간다.

1초 R

G   R
G GR R

이때 GR부분은 꽃으로 변하면서 R은 큐에 들어가지 않는다.

2초 G

G G  
G F R

1행1열의 G에서 오른쪽으로 퍼지긴 하지만, F에 남아있던 G에 의해 위로 G가 퍼진다. → 현재칸이 꽃이거나 호수면 퍼트리지 않도록 조건 추가

 

<중요 정리>

X

'APS' 카테고리의 다른 글

BOJ9441 Cash Cow  (1) 2022.10.08
BOJ17779 게리맨더링2  (0) 2022.07.24
BOJ14503 로봇청소기  (0) 2022.06.26
BOJ9205 맥주 마시면서 걸어가기  (0) 2022.06.26
BOJ2573 빙산  (0) 2022.06.26