🔗 문제 링크: 백준 18430번 - 무기 공학
N × M
크기의 격자에서 부메랑 모양의 무기를 배치하여 최대한 강한 무기를 제작하는 문제.2 × 중심값 + 나머지 두 값
으로 점수를 계산.🚀 백트래킹을 사용하여 모든 가능한 부메랑 배치를 탐색하고, 최댓값을 갱신하는 방식으로 해결.
N × M
에서 부메랑을 배치하는 모든 경우를 탐색.O(4^(N×M))
로 경우의 수가 기하급수적으로 증가 → 비효율적!import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.StringTokenizer;
public class Main {
private static StringTokenizer st;
private static BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
private static int N, M;
private static int[][] map;
private static boolean[][] visited;
private static int[][][] boomerang = {
{{0, -1}, {0, 0}, {1, 0}}, // └ 모양
{{0, -1}, {0, 0}, {-1, 0}}, // ┌ 모양
{{-1, 0}, {0, 0}, {0, 1}}, // ┐ 모양
{{0, 1}, {0, 0}, {1, 0}} // ┘ 모양
};
private static int answer;
public static void main(String[] args) throws IOException {
setting();
dfs(0, 0, 0);
System.out.println(answer);
}
private static void dfs(int x, int y, int sum) {
if (x == N - 1 && y == M) {
answer = Math.max(answer, sum);
return;
}
// 다음 좌표 계산
x += y / M;
y %= M;
// 4가지 부메랑 배치 시도
for (int i = 0; i < 4; i++) {
int bx1 = x + boomerang[i][0][0];
int by1 = y + boomerang[i][0][1];
int bx2 = x + boomerang[i][1][0];
int by2 = y + boomerang[i][1][1];
int bx3 = x + boomerang[i][2][0];
int by3 = y + boomerang[i][2][1];
if (bx1 < 0 || bx1 >= N || by1 < 0 || by1 >= M ||
bx2 < 0 || bx2 >= N || by2 < 0 || by2 >= M ||
bx3 < 0 || bx3 >= N || by3 < 0 || by3 >= M) continue;
if (visited[bx1][by1] || visited[bx2][by2] || visited[bx3][by3]) continue;
// 방문 처리
visited[bx1][by1] = visited[bx2][by2] = visited[bx3][by3] = true;
int value = getValue(bx1, by1, bx2, by2, bx3, by3);
dfs(x, y + 1, sum + value);
// 백트래킹 (원상 복구)
visited[bx1][by1] = visited[bx2][by2] = visited[bx3][by3] = false;
}
// 부메랑을 사용하지 않는 경우도 고려
dfs(x, y + 1, sum);
}
private static int getValue(int bx1, int by1, int bx2, int by2, int bx3, int by3) {
return map[bx1][by1] + map[bx2][by2] * 2 + map[bx3][by3];
}
private static void setting() throws IOException {
st = new StringTokenizer(br.readLine());
N = Integer.parseInt(st.nextToken());
M = Integer.parseInt(st.nextToken());
map = new int[N][M];
visited = new boolean[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());
}
}
}
}
현재 dfs(x, y, sum)
에서 각 열(y)을 모두 탐색한 후 다음 행(x)으로 이동하는 방식을 사용.
dfs(0, 0, 0)
시작 → y
를 끝까지 탐색 → x
증가x += y / M; y %= M;
를 활용해 자동으로 다음 행으로 이동하도록 개선.visited[][]
를 통해 부메랑 배치 가능 여부를 빠르게 확인하여 불필요한 연산 제거.visited[][]
복구) 적용.함수 | 역할 |
---|---|
dfs(x, y, sum) | 현재 좌표 (x, y) 에서 부메랑을 배치하면서 탐색 |
getValue(bx1, by1, bx2, by2, bx3, by3) | 부메랑 배치 시 무기 점수 계산 |
setting() | 입력 처리 및 초기화 |
4^(N*M)
의 경우의 수를 백트래킹으로 탐색 N, M
의 최대 크기가 5이므로 충분히 백트래킹으로 해결 가능✅ DFS + 백트래킹을 활용하여 최적의 부메랑 배치를 탐색
✅ 방문 체크(visited[][]
)를 활용하여 불필요한 연산 감소
✅ x += y / M; y %= M;
활용하여 탐색 흐름을 최적화
안녕하세요~! 백준 푸시느라 고생많으셨습니다. 글을 참 체계적으로 잘 작성하시네요!! 👍 혹시 백준에서 푼 문제를 효율적으로 복습하고 정리하는 데 관심 있으시다면, https://mycodingtest.com 서비스를 한번 이용해보세요! 제가 진행한 개인 프로젝트인데 벨로그에서 백준 푸시는 분들께 댓글로 이렇게 홍보를 하고있습니다. 코테 준비에 도움이 되면 좋겠습니다 😊