algoqna

[BOJ 17135] 캐슬 디펜스 본문

프로그래밍/기타 문제풀이

[BOJ 17135] 캐슬 디펜스

kkalgo 2023. 5. 18. 08:41

 

1. 궁수 3명을 각 행의 m열에 3명을 배치시킬 수 있다, --> mC3의 경우의 수로 궁수를 배치

 

2. 궁수가 공격할 수 있는 적은 거리가 D이하인 적에서 가장 가까운 적, 그러한 적이 여러명이면 가장 왼쪽에 있는 적을 우선적으로 쏜다.

    * 즉, 왼쪽 -> 위 -> 오른쪽 순으로 탐색(BFS)하여 제일 먼저 만나는 적이 가장 가까운 적이다.

    * 최우선으로 가까운 적은 궁수 바로 위에 위치하는 적이므로 시작점(궁수의 바로 위 지점)을 큐에 넣고 탐색 시작

 

3. 궁수는 동시에 공격하며 같은 적을 공격할 수 있다

    * 3명의 궁수가 공격할 수 있는 가장 가까운 적을 3명이 모두 선택하고 나서 적을 죽여야 한다. 

    * 1명이 적 선택하고 바로 죽이고 다른 1명이 적 선택하고.. 안된다는 것.  

 

4. 궁수의 공격이 끝나면 적이 1칸씩 성으로 이동한다

    * 거꾸로 생각해서 궁수의 위치를 1칸씩 위로 옮기면 적들을 옮기지 않아도 된다.

 

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

public class Main {

	static int[][] original; // 원본 배열 
	static int n,m,d; // 행, 열, 궁수의 사격거리
	static int[] placeArcher = new int[3]; // 궁수 배치시키기 위한 배열
	static int ans = 0;

	static int[] Xarr = {0,-1,0};
	static int[] Yarr = {-1,0,1};
	
	static class Enemy{
		
		int x;
		int y;
		
		public Enemy(int x, int y) {
			
			this.x=x;
			this.y=y;
		}

	}
	
	public static void main(String[] args) throws NumberFormatException, IOException {
		// TODO Auto-generated method stub

		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		BufferedWriter wr = new BufferedWriter(new OutputStreamWriter(System.out));
		StringBuilder sb = new StringBuilder();
		
		String[] input = br.readLine().split(" ");
		n = Integer.parseInt(input[0]);
		m = Integer.parseInt(input[1]);
		d = Integer.parseInt(input[2]);
		original = new int [n+1][m];
		
		for (int i=0; i< n; i++) {
			input = br.readLine().split(" ");
			for (int j=0; j<m; j++) {
				original[i][j] = Integer.parseInt(input[j]);
			}
		}
		
		Combination(0,0); // 궁수 배치시키는 방법을 조합으로 구한다
		
		sb.append(ans);
		wr.write(sb.toString());
		wr.close();
		br.close();
	}
	
	private static void Combination(int start, int cnt) {
		
		if (cnt == 3) {
			Attack();
			return;
		}
		
		for (int i= start; i < m; i++) {
			placeArcher[cnt] = i;
			Combination(i+1, cnt+1);
		}
		
		
	}
	private static void Attack() {
		
		// 1. 배열 복사
		int[][] copyArr = new int [n+1][m];
	
		for (int i=0; i<n; i++) {
			for (int j=0; j<m; j++) 
				copyArr[i][j] = original[i][j];
		}
		
		// 2. 계산 로직 시작
		int killCount = 0;
		
		List<Enemy> list= new ArrayList<>();
		
		for (int i=n-1; i>=0; i--) { // 맨 아래에서부터
			
			for (int archer = 0; archer < 3; archer++) { // 각각의 archer가
				Enemy temp = Dead(i,placeArcher[archer],copyArr); // 가장 가까운 적을 찾으러 가보는데
				if (temp == null) continue; // 없으면 상관없다.
				
				list.add(temp); // 죽일 수 있는 적이 있었다면 add
			}
			
			for (int j=0; j<list.size(); j++) { // 추가된 적의 개수 만큼
				
				int x = list.get(j).x;
				int y = list.get(j).y;
				
				if (copyArr[x][y] == 1) { // 살아있는 적, 중복이 있었다 하더라도 
					killCount++; // 최초만 killCount++
					copyArr[x][y] = 0;
				}
			}
			
		}
		
		ans = Math.max(ans, killCount);
		
	}
	private static Enemy Dead(int x, int y, int[][] copyArr) {
		
		Queue<Enemy> q = new ArrayDeque<>();
		boolean[][] visited = new boolean[n][m];
		
		q.add(new Enemy(x,y));
		Enemy temp;
		int nx,ny;
		while(!q.isEmpty()) {
			
			temp = q.poll();
			
			if(visited[temp.x][temp.y]) continue;
			
			if(copyArr[temp.x][temp.y] == 1) {
				return temp;
			}
			
			visited[temp.x][temp.y] = true;
			
			for (int i=0; i<3; i++) { // 왼쪽 위 오른쪽 탐색으로 문제 조건에 의해 왼쪽부터 훑을 수 있도록 bfs탐색이다.
				nx = temp.x + Xarr[i];
				ny = temp.y + Yarr[i];
				if (isIn(nx,ny) && CalculateDist(x+1, y, nx, ny)) {
					q.add(new Enemy(nx,ny));
				}
			}
		}
		
		return null;
	}

	private static boolean isIn(int nx, int ny) {
		
		if (nx < 0 || nx >= n || ny < 0 || ny >= m) return false;
		
		return true;
	}

	private static boolean CalculateDist(int archerRow, int archerCol, int enemyRow, int enemyCol) {
		
		int dist = Math.abs(archerRow - enemyRow) + Math.abs(archerCol - enemyCol);
		
		if (dist <= d) {
			return true;
		}
		
		return false;
	}
	


}

 

 

 

 

'프로그래밍 > 기타 문제풀이' 카테고리의 다른 글

[BOJ 5427] 불!  (2) 2023.05.21
[BOJ 2512] 예산  (0) 2023.05.19
[BOJ 22856] 트리 순회  (0) 2023.05.16
[BOJ 11663] 선분 위의 점  (0) 2023.05.15
[BOJ 21608] 상어 초등학교  (0) 2023.05.12