꾸물꾸물 졔의 개발공부
[백준] 17135 캐슬 디펜스 - JAVA 본문
https://www.acmicpc.net/problem/17135
17135번: 캐슬 디펜스
첫째 줄에 격자판 행의 수 N, 열의 수 M, 궁수의 공격 거리 제한 D가 주어진다. 둘째 줄부터 N개의 줄에는 격자판의 상태가 주어진다. 0은 빈 칸, 1은 적이 있는 칸이다.
www.acmicpc.net
알고리즘
- 구현 + 시뮬레이션
- 3명의 궁수 위치를 조합으로 찾아서, 모든 경우의 수에 대해 공격 시뮬레이션
- bfs 로 궁수 위치로부터 최단 거리에 있는 적 찾아서 공격
- 한 턴 마다 두명 이상의 궁수가 같은 적을 공격할 수 있기 때문에 적을 -1로 바꾼 후, 한 턴이 끝난 후 0으로 바꿔줌
- 단, 처음 입력받은 격자 map을 그대로 사용하지 않고, 복사해둔 copymap에 시뮬레이션 구동
소스 코드
import java.util.*;
import java.io.*;
public class Solution_BaekJoon_17135 {
private static int N,M,D;
private static int[][] map;
private static boolean[][] visited; //bfs 탐색을 위한 방문 체크
private static boolean[] picked;
private static int attack_max= Integer.MIN_VALUE;
public static void main(String[] args) throws Exception {
BufferedReader br= new BufferedReader(new InputStreamReader(System.in));
StringTokenizer st;
st= new StringTokenizer(br.readLine(), " ");
N= Integer.parseInt(st.nextToken());
M= Integer.parseInt(st.nextToken());
D= Integer.parseInt(st.nextToken());
picked = new boolean[M];
map = new int[N][M];
for(int i=0; i<N; i++) {
st= new StringTokenizer(br.readLine(), " ");
for(int j=0; j<M; j++) {
map[i][j]= Integer.parseInt(st.nextToken());
}
}
setComb(0, 3);
System.out.println(attack_max);
}//end of main
//궁수 3명 배치하기
private static void setComb(int index, int cnt) {
//3명 모두 배치했을 경우,
if(cnt==0) {
int count= attack(); //공격 시작
attack_max= Math.max(count, attack_max); //최대 값 갱신
return ;
}
for(int i=index; i<M; i++) {
picked[i]=true;
setComb(i+1, cnt-1);
picked[i]=false;
}
}
static class Point implements Comparable<Point>{
int x; int y;
int dis;
public Point(int x, int y, int dis) {
this.x= x;
this.y= y;
this.dis= dis;
}
@Override
public int compareTo(Point o) {
if(this.dis == o.dis) {
return this.y - o.y;
}
return this.dis- o.dis;
}
}
static int dx[]= {-1,0,0};
static int dy[]= {0,1,-1};
//공격 시작하기
private static int attack(){
int enemy_cnt =0; //이번 공격에 제거할 수 있는 적의 수
PriorityQueue<Point> que;
int[][] copymap = new int[N][M]; //이번 턴에서 공격할 지도
for(int i=0; i<N; i++) {
for(int j=0; j<M; j++)
copymap[i][j] = map[i][j];//원본배열 복사
}
//모든 적이 없어질 때까지 반복
while(!isFinish(copymap)) {
for(int i=0; i<picked.length; i++) {
//궁수가 있는 곳에서 공격 시작
if(picked[i]) {
que= new PriorityQueue<>();
visited= new boolean[N][M]; //bfs 탐색을 위한 방문체크
que.add(new Point(N-1, i, 1));
//해당 궁수와 가장 가까운 적 찾기
while(!que.isEmpty()) {
Point p = que.poll();
int x= p.x;
int y= p.y;
int dis= p.dis;
//가장 가까운 적 !
if(copymap[x][y] != 0 && dis <= D) {
//처음 공격 받는 적 (-1이면 다른 궁수도 이미 공격)
if(copymap[x][y]==1) {
enemy_cnt ++;
copymap[x][y]=-1;
}
break;
}
for(int d=0; d<3; d++) {
int nx = x+dx[d];
int ny = y+dy[d];
if(isOut(nx, ny) || visited[nx][ny]) continue;
visited[nx][ny] = true;
que.add(new Point(nx, ny, dis+1));
}
}
}
}
//적들 아래로 한칸씩 내려오기
for(int i=N-1; i>=1; i--) {
for(int j=0; j<M; j++) {
copymap[i][j] = copymap[i-1][j];
}
}
Arrays.fill(copymap[0], 0);
}//end of while
return enemy_cnt;
}
private static boolean isOut(int x, int y) {
return x<0 || x>=N || y<0 || y>=M;
}
//모든 적이 격자판에서 제외됬으면 true 반환
private static boolean isFinish(int[][] copymap) {
boolean flag = true;
for(int i=0; i<N; i++) {
for(int j=0;j <M; j++) {
if(copymap[i][j] ==-1) copymap[i][j] = 0; //적 -1 → 0
if(copymap[i][j] ==1 ) flag= false;
}
}
return flag;
}
}//end of class
'알고리즘 > 백준' 카테고리의 다른 글
[백준] 1239 차트 - JAVA (1) | 2023.06.09 |
---|---|
[백준] 1195 킥다운 - JAVA (0) | 2023.06.08 |
[백준] 2252 줄 세우기 - JAVA (1) | 2023.05.25 |
[백준] 1976 여행 가자 - JAVA (0) | 2023.05.24 |
[백준] 14846 직사각형과 쿼리 - JAVA (0) | 2023.05.18 |