본문 바로가기
Algorithm/Baekjoon

Baekjoon 17135 캐슬 디펜스 JAVA

by Hunveloper 2022. 4. 15.
728x90
 

17135번: 캐슬 디펜스

첫째 줄에 격자판 행의 수 N, 열의 수 M, 궁수의 공격 거리 제한 D가 주어진다. 둘째 줄부터 N개의 줄에는 격자판의 상태가 주어진다. 0은 빈 칸, 1은 적이 있는 칸이다.

www.acmicpc.net

문제

캐슬 디펜스는 성을 향해 몰려오는 적을 잡는 턴 방식의 게임이다. 게임이 진행되는 곳은 크기가 N×M인 격자판으로 나타낼 수 있다. 격자판은 1×1 크기의 칸으로 나누어져 있고, 각 칸에 포함된 적의 수는 최대 하나이다. 격자판의 N번행의 바로 아래(N+1번 행)의 모든 칸에는 성이 있다.

성을 적에게서 지키기 위해 궁수 3명을 배치하려고 한다. 궁수는 성이 있는 칸에 배치할 수 있고, 하나의 칸에는 최대 1명의 궁수만 있을 수 있다. 각각의 턴마다 궁수는 적 하나를 공격할 수 있고, 모든 궁수는 동시에 공격한다. 궁수가 공격하는 적은 거리가 D이하인 적 중에서 가장 가까운 적이고, 그러한 적이 여럿일 경우에는 가장 왼쪽에 있는 적을 공격한다. 같은 적이 여러 궁수에게 공격당할 수 있다. 공격받은 적은 게임에서 제외된다. 궁수의 공격이 끝나면, 적이 이동한다. 적은 아래로 한 칸 이동하며, 성이 있는 칸으로 이동한 경우에는 게임에서 제외된다. 모든 적이 격자판에서 제외되면 게임이 끝난다. 

게임 설명에서 보다시피 궁수를 배치한 이후의 게임 진행은 정해져있다. 따라서, 이 게임은 궁수의 위치가 중요하다. 격자판의 상태가 주어졌을 때, 궁수의 공격으로 제거할 수 있는 적의 최대 수를 계산해보자.

격자판의 두 위치 (r1, c1), (r2, c2)의 거리는 |r1-r2| + |c1-c2|이다.

입력

첫째 줄에 격자판 행의 수 N, 열의 수 M, 궁수의 공격 거리 제한 D가 주어진다. 둘째 줄부터 N개의 줄에는 격자판의 상태가 주어진다. 0은 빈 칸, 1은 적이 있는 칸이다.

출력

첫째 줄에 궁수의 공격으로 제거할 수 있는 적의 최대 수를 출력한다.

풀이

1. 조합을 이용하여 궁수가 위치할 수 있는 모든 위치를 찾는다.

 -> copymap()을 이용하여 항상 초기의 상태에서 적들을 찾는 동작을 수행시킴

 -> copymap()을 이용해 생성된 맵을 simul()에서 이용

2. 받아온 map을 이용하여 열우선 탐색을 이용하여 적을 탐색한다.

 -> kill[][] 배열의 행은 n번째 궁수, 열은 적군의 위치를 저장한다.

3. 59번째의 for문에서 모든 궁수들의 위치를 돌면서 combi에서 지정된 궁수이면 거리탐색을 실시하며 가장 가까운 적군을 찾는다.

4. 54번째 줄에서 시간에 대한 변수를 두어 적군들과의 거리를 계산할때 time을 뺌으로 상대적으로 적군이 다가오는 계산을 할 수 있다.

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

public class Main {
	static int n, m, d, ans;
	static boolean[] archors;
	static int[][] ori, work;

	public static void main(String[] args) 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());
		d = Integer.parseInt(st.nextToken());
		ori = new int[n+1][m+1];
		work = new int[n+1][m+1];
		archors = new boolean[m];
		for (int i = 0; i < n; i++) {
			st = new StringTokenizer(br.readLine());
			for (int j = 0; j < m; j++)
				ori[i][j] = Integer.parseInt(st.nextToken());
		}

		combi(0, 0);

		System.out.println(ans);

	}

	public static void copymap() {
		for (int i = 0; i < n; i++)
			for (int j = 0; j < m; j++)
				work[i][j] = ori[i][j];
	}

	public static void combi(int s, int depth) {
		if (depth == 3) {
			copymap(); // ori -> work로 맵복사
			simul(); // work 사용
			return;
		}
		for (int i = s; i < m; i++) {
			if (!archors[i]) {
				archors[i] = true;
				combi(i, depth + 1);
				archors[i] = false;
			}
		}
	}

	public static void simul() {
		int tempsum = 0;
		for (int time = 0; time < n; time++) {
			int[][] kill = new int[3][2];
			for(int i=0;i<3;i++)
				kill[i][0]=n;
			int loc = 0;
			for (int archor = 0; archor < m; archor++) {
				if (archors[archor]) {

					int mindist = 9999;
					for (int j = 0; j < m; j++) {
						for (int i = n - time - 1; i >= 0; i--) {
							int tempdist = Math.abs(n - time - i) + Math.abs(archor - j);
							if (work[i][j] == 1 && tempdist <= d && tempdist < mindist) {
								mindist = tempdist;
								kill[loc][0] = i;
								kill[loc][1] = j;
							}
						}
					}
					loc++;
				}
			}
			for (int i = 0; i < 3; i++) {
				if (work[kill[i][0]][kill[i][1]] == 1) {
					work[kill[i][0]][kill[i][1]] = 0;
					tempsum++;
				}
			}
		}
		if (tempsum > ans)
			ans = tempsum;
	}
}

 

728x90
728x90

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

Baekjoon 15802 타노스 Python  (0) 2022.04.15
Baekjoon 1912 연속합 JAVA  (0) 2022.04.15
Baekjoon 14502 연구소 JAVA  (0) 2022.04.13
Baekjoon 1932 정수 삼각형 JAVA  (0) 2022.04.13
Baekjoon 2630 색종이 만들기 JAVA  (0) 2022.04.13

댓글