캐슬 디펜스
백준 17135: 캐슬 디펜스
풀이
재귀함수를 사용하여 궁수 3명이 배치 될 열을 조합하기
- combi(int[] tmp, int[] sel, int c, int idx)
- tmp : 궁수가 배치 될 수 있는 모든 열이 들어 있는 배열
- sel : 3명의 궁수가 배치 될 3개의 열의 조합 배열
- c : 조합으로 선택되는 열의 위치를 담을 배열(sel)의 인덱스 번호
- idx : 열의 위치가 들어있는 배열(tmp)의 인덱스 번호
소스코드
package 백준;
import java.util.ArrayList;
import java.util.Scanner;
public class Main {
static class Enemy {
int r, c;
Enemy(int r, int c) {
this.r = r;
this.c = c;
}
@Override
public String toString() {
return "Enemy [r=" + r + ", c=" + c + "]";
}
}
static ArrayList<Enemy> EnemyList = new ArrayList<>();
static int N;
static int M;
static int D;
static int[][] map;
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
N = sc.nextInt(); // 행의 수
M = sc.nextInt(); // 열의 수
D = sc.nextInt(); // 공격 거리 제한
map = new int[N][M];
for (int i = 0; i < N; i++) {
for (int j = 0; j < M; j++) {
map[i][j] = sc.nextInt();
if (map[i][j] == 1)
EnemyList.add(new Enemy(i, j));
}
}
// 궁수가 배치 될 열을 조합으로 찾기
int[] tmp = new int[M];
for (int i = 0; i < M; i++) {
tmp[i] = i;
}
combi(tmp, new int[3], 0, 0);
System.out.println(max);
}
static int max = 0;
static void combi(int[] tmp, int[] sel, int c, int idx) {
if (c == sel.length) {
// 공격거리 D만큼 적을 죽여
ArrayList<Enemy> copyEnemy = new ArrayList<>();
for (int i = 0; i < EnemyList.size(); i++) {
copyEnemy.add(new Enemy(EnemyList.get(i).r, EnemyList.get(i).c));
}
boolean flag = true;
int cnt = 0;
while(flag) {
ArrayList<Enemy> die = new ArrayList<>();
for (int i = 0; i < sel.length; i++) {
int minC = M;
int minR = 0;
int dis = 0;
int min = D;
for (int k = 0; k < copyEnemy.size(); k++) {
dis = Math.abs(copyEnemy.get(k).r - N) + Math.abs(copyEnemy.get(k).c - sel[i]);
if (dis < min) {
min = dis;
minR = copyEnemy.get(k).r;
minC = copyEnemy.get(k).c;
}
if (dis == min) {
if (minC > copyEnemy.get(k).c) {
minR = copyEnemy.get(k).r;
minC = copyEnemy.get(k).c;
}
}
}
if (minC < M)
die.add(new Enemy(minR, minC)); // 죽을 애들을 리스트에 담아
}
// 죽인 적의 수를 먼저 세자
int tmpR = -1;
int tmpC = -1;
for (int i = 0; i < die.size(); i++) {
if (tmpR != die.get(i).r || tmpC != die.get(i).c) {
cnt++;
}
tmpR = die.get(i).r;
tmpC = die.get(i).c;
}
// 적을 죽이고(적리스트에서 죽을애들리스트에 있는 거 찾아서 지우기)
int tmpsize = copyEnemy.size();
for(int i=0; i<die.size(); i++) {
for(int j=tmpsize-1; j>=0; j--) {
if(copyEnemy.get(j).r == die.get(i).r && copyEnemy.get(j).c == die.get(i).c) {
copyEnemy.remove(j);
}
}
tmpsize = copyEnemy.size();
}
// 적을 한칸씩 내리기
int size = copyEnemy.size();
for (int i = 0; i < size; i++) {
if (copyEnemy.get(i).r + 1 < N) {
copyEnemy.add(new Enemy(copyEnemy.get(i).r + 1, copyEnemy.get(i).c));
}
}
for (int i = 0; i < size; i++) {
copyEnemy.remove(0);
}
if (copyEnemy.size() == 0)
flag = false;
}
max = Math.max(max, cnt);
return;
}
if (idx == tmp.length)
return;
sel[c] = tmp[idx];
combi(tmp, sel, c + 1, idx + 1);
combi(tmp, sel, c, idx + 1);
}
}