코딩/알고리즘
[백준][자바][17135]캐슬디펜스
알파세
2019. 10. 23. 23:04
1. 궁수의 위치를 dfs 세팅함
2. 궁수 위치가 세팅되면 적들과의 distance를 재서 죽일수 있는 적들을 찾아둠
3. 적들 죽이고 카운트
4. 적이동
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.LinkedList;
import java.util.PriorityQueue;
import java.util.Queue;
import java.util.StringTokenizer;
class Archer {
int y;
int x;
Archer(int y, int x) {
this.y = y;
this.x = x;
}
}
class Enemy implements Comparable {
int y;
int x;
int distance;
Enemy(int y, int x, int distance) {
this.y = y;
this.x = x;
this.distance = distance;
}
// 제일 왼쪽
// 그중에서도
@Override
public int compareTo(Enemy target) {
if (this.distance < target.distance) { //거리가 크면
return -1;
}
else if (this.distance > target.distance) {
return 1;
}
else { // 같은 경우
if (this.x < target.x) {
return -1;
}
else if (this.x == target.x) {
return 0;
}
else {
return 1;
}
}
}
}
public class Main_backjoon_17135_캐슬디펜스 {
static int ANSWER = 0;
static int N;
static int M;
static int D;
static int[][] MAP;
static boolean[] VISITED;
static Queue qe = new LinkedList();
static Queue q = new LinkedList();
static PriorityQueue pqe = new PriorityQueue();
public static void main(String[] args) 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());
D = Integer.parseInt(st.nextToken());
MAP = new int[N + 1][M];
VISITED = new boolean[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());
}
}
setPosition(0,0);
System.out.println(ANSWER);
}
public static Integer calDistance(int y1, int x1, int y2, int x2) {
int distance = Math.abs(y1 - y2) + Math.abs(x1 - x2);
return distance;
}
public static int findEnemy() {
int count = 0;
//맵 복사
for(int i= 0; i < N; i++) {
for(int j = 0; j < M; j++) {
if (MAP[i][j] == 1) {
qe.add(new Enemy(i, j, 0));
}
}
}
while(!qe.isEmpty()) {
int[][] TEMPENEMY = new int[N][M];
LinkedList list = new LinkedList();
//1. 적 찾기
for(Archer archar : q) {
for(Enemy enemy : qe) {
int r = enemy.y;
int c = enemy.x;
int distance = calDistance(r, c, archar.y, archar.x);
if ( distance <= D ) {
pqe.add(new Enemy(r,c,distance));
}
}
//가장 거리가 가깝고 제일 왼쪽에 있는 적 꺼내기
if(!pqe.isEmpty()) {
Enemy enemy = pqe.poll();
list.add(new Enemy(enemy.y, enemy.x, enemy.distance)); //죽일 enemy 들
pqe.clear();
}
}
//한개만 새기
for(int i = 0; i < list.size(); i++ ) {
Enemy e = list.get(i);
TEMPENEMY[e.y][e.x] += 1;
if( TEMPENEMY[e.y][e.x] == 1) {
count += 1;
}
}
//아까 뺸애들 죽여
int qsize = qe.size();
for(int s = 0; s < qsize; s++) {
Enemy e = qe.poll();
boolean flag = false;
for(Enemy enemy : list) {
// 같은게 있으면
if(enemy.y == e.y && enemy.x == e.x ) {
flag = true;
}
}
if(!flag) {
qe.add(e);
}
}
//enemy move;
move();
}
return count;
}
/* 만약에 다음 라인에 성에 도착했다면 */
public static boolean isRange(int yy) {
if (yy == N) {
return true;
} else {
return false;
}
}
// 3.enemy move;
public static void move() {
int qsize = qe.size();
for(int s = 0; s < qsize; s++) {
Enemy enemy = qe.poll();
//무조건 바로 밑으로 하강
int yy = enemy.y + 1;
int xx = enemy.x;
int distance = enemy.distance;
if(isRange(yy)) { // 삭제
continue;
}else {
qe.add(new Enemy(yy,xx, distance));
}
}
}
// 1. 궁수의 자리를 배치한다
public static void setPosition(int depth, int start ) {
// 궁수 배치
if (depth == 3) {
// Archer 배치
for(int i = 0; i < M; i++) {
if(VISITED[i]) {
q.add(new Archer(N, i));
}
}
int tempAnswer = findEnemy();
ANSWER = Math.max(ANSWER, tempAnswer);
q.clear();
return;
}
for (int i = start; i < M; i++) {
if (!VISITED[i]) {
VISITED[i] = true;
setPosition(depth + 1, i);
VISITED[i] = false;
}
}
}
}