https://www.acmicpc.net/problem/12100
12100번: 2048 (Easy)
첫째 줄에 보드의 크기 N (1 ≤ N ≤ 20)이 주어진다. 둘째 줄부터 N개의 줄에는 게임판의 초기 상태가 주어진다. 0은 빈 칸을 나타내며, 이외의 값은 모두 블록을 나타낸다. 블록에 쓰여 있는 수는 2
www.acmicpc.net
- 상하좌우로 총 5번 움직였을 때 그래프에 있는 가장 큰 수를 구하는 문제이다. 따라서 상하좌우로 5번 움직이는 조합을 찾기 위해 재귀를 사용해야 한다.
- 그리고 상하좌우로 움직이는 로직을 구현해야 한다.
- 기존 배열을 보고 새로운 배열을 만들어야 한다.
- 새로운 배열에 값을 채울 인덱스인 fillIdx와 기존 배열과 값을 비교할 인덱스인 checkIdx가 필요하다.
- 기존 배열의 값 num과 새로운 배열의 checkIdx번째 값이 같으면,
- 수를 합쳐야하므로 checkIdx번째 값을 2배한다.
- 해당 인덱스는 이미 한 번 합쳐졌으므로 다음에는 체크할 필요가 없다. 따라서 checkIdx의 값을 1 증가시키거나 감소시킨다.
- 기존 배열의 값 num과 새로운 배열의 checkIdx번째 값이 같지 않으면,
- fillIdx 위치에 num을 저장한다.
- 값이 합쳐지지 않고 새로운 위치에 추가되었으므로 fillIdx의 값을 1 증가시키거나 감소시킨다.
- checkIdx는 fillIdx보다 1 작거나 커야하므로 변경시킨다.
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.*;
// 시간복잡도: 4^5 + O(N^2) (dfs + 그래프 탐색) = 4^5 + 400
public class Main {
static int n;
static int[][] map;
static int answer = 0;
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
n = Integer.parseInt(br.readLine());
map = new int[n][n];
for (int i = 0; i < n; i++) {
StringTokenizer st = new StringTokenizer(br.readLine());
for (int j = 0; j < n; j++) {
map[i][j] = Integer.parseInt(st.nextToken());
}
}
dfs(0, copyMap(map));
System.out.println(answer);
}
private static void dfs(int count, int[][] map) {
if (count == 5) {
answer = Math.max(getMax(map), answer);
return;
}
// 위
dfs(count + 1, up(copyMap(map)));
// 아래
dfs(count + 1, down(copyMap(map)));
// 오른쪽
dfs(count + 1, right(copyMap(map)));
// 왼쪽
dfs(count + 1, left(copyMap(map)));
}
private static int[][] up(int[][] map) {
int[][] newMap = new int[n][n];
for (int i = 0; i < n; i++) {
int fillIdx = 0;
int checkIdx = 0;
for (int j = 0; j < n; j++) {
int num = map[j][i];
if (num == 0) continue;
// 합치는 경우
if (newMap[checkIdx][i] == num) {
newMap[checkIdx][i] = num * 2;
checkIdx++;
}
// 합치지 않는 경우
else {
newMap[fillIdx][i] = num;
fillIdx++;
checkIdx = fillIdx - 1;
}
}
}
return newMap;
}
private static int[][] down(int[][] map) {
int[][] newMap = new int[n][n];
for (int i = 0; i < n; i++) {
int fillIdx = n - 1;
int checkIdx = n - 1;
for (int j = n - 1; j >= 0; j--) {
int num = map[j][i];
if (num == 0) continue;
if (newMap[checkIdx][i] == num) {
newMap[checkIdx][i] = num * 2;
checkIdx--;
} else {
newMap[fillIdx][i] = num;
fillIdx--;
checkIdx = fillIdx + 1;
}
}
}
return newMap;
}
private static int[][] right(int[][] map) {
int[][] newMap = new int[n][n];
for (int i = 0; i < n; i++) {
int fillIdx = n - 1;
int checkIdx = n - 1;
for (int j = n - 1; j >= 0; j--) {
int num = map[i][j];
if (num == 0) continue;
if (newMap[i][checkIdx] == num) {
newMap[i][checkIdx] = num * 2;
checkIdx--;
} else {
newMap[i][fillIdx] = num;
fillIdx--;
checkIdx = fillIdx + 1;
}
}
}
return newMap;
}
private static int[][] left(int[][] map) {
int[][] newMap = new int[n][n];
for (int i = 0; i < n; i++) {
int fillIdx = 0;
int checkIdx = 0;
for (int j = 0; j < n; j++) {
int num = map[i][j];
if (num == 0) continue;
if (newMap[i][checkIdx] == num) {
newMap[i][checkIdx] = num * 2;
checkIdx++;
} else {
newMap[i][fillIdx] = num;
fillIdx++;
checkIdx = fillIdx - 1;
}
}
}
return newMap;
}
private static int getMax(int[][] map) {
int max = 0;
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
max = Math.max(max, map[i][j]);
}
}
return max;
}
private static int[][] copyMap(int[][] map) {
int[][] copy = new int[n][n];
for (int i = 0; i < n; i++) {
copy[i] = map[i];
}
return copy;
}
}
'CS > Algorism' 카테고리의 다른 글
[백준] 11055. 가장 큰 증가하는 부분 수열 (0) | 2024.01.09 |
---|---|
[백준] 5427. 불 (1) | 2024.01.06 |
[백준] 1697. 숨바꼭질 (0) | 2023.12.29 |
[백준] 1541. 잃어버린 괄호 (0) | 2023.12.29 |
[백준] 4179. 불! (0) | 2023.12.28 |