문제
https://softeer.ai/practice/7727
자세한 내용은 원문 코드를 참조할 것.
풀이
처음에는 dp[Idx][R][C]를 통해, 각 친구(idx)별 경로를 추적하여 dp를 사용하고자 했으나,
백트래킹으로 각 위치별 수집량을 점유한 뒤, 이를 다음 친구로 적용하는 로직으로 풀이를 변경하였다.
풀이는 다음과 같다.
1. 0번째 인덱스(첫번째 친구)를 먼저 탐색한다.
2. if 기저조건 : time = 3초일 경우 해당 값을 저장한 채로, idx를 증가한 뒤 재귀 함수를 시행한다(다음 친구 호출)
3. 최종 조회 시 최대값을 비교한다.
4. 백트래킹을 통해 가지치기를 수행한다.
자세한 내용은 코드를 참조할 것
코드
import java.io.*;
import java.util.*;
public class Main {
static final int[] DR = new int[] {0, 1, 0, -1};
static final int[] DC = new int[] {1, 0, -1, 0};
static int N, M;
static int[][] map;
static boolean[][][] visit;
static List<int[]> friends = new ArrayList<>();
static int maxResult = 0;
public static void main(String[] args) throws Exception {
input();
int r = friends.get(0)[0];
int c = friends.get(0)[1];
dfs(0, 0, 0, r, c);
System.out.println(maxResult);
}
//
public static void dfs(int time, int idx, int res, int r, int c) {
if(checkVisit(r, c)) res += map[r][c]; //'전체 Visit'에서 아무도 방문하지 않은 경우 더하기
visit[idx][r][c] = true; //방문 처리
if (time == 3) { // 기저조건: 3초 전부 수집
if (idx + 1 == M) { // 마지막 친구일 경우 결과 갱신
maxResult = Math.max(maxResult, res);
} else {
// 다음 친구로 넘어가는 로직
int nextIdx = idx + 1; // 인덱스 증가
int nextR = friends.get(nextIdx)[0]; // 다음 친구 좌표
int nextC = friends.get(nextIdx)[1]; //
dfs(0, nextIdx, res, nextR, nextC); // 현재 res값을 가지고 다음 친구로 이동
}
visit[idx][r][c] = false; // 방문 처리 해제 (백트래킹)
return;
}
for(int i = 0; i < 4; i++) {
int nr = r + DR[i];
int nc = c + DC[i];
if(cantGo(nr, nc) || visit[idx][nr][nc]) continue; //방문했거나 갈 수 없음
dfs(time + 1, idx, res, nr, nc);
}
visit[idx][r][c] = false; //방문 처리 해제(가지치기)
}
public static boolean checkVisit(int r, int c) {
for(int i = 0; i < M; i++) {
if(visit[i][r][c]) return false; //이미 누군가 방문했음
}
return true; //아무도 방문하지 않음
}
public static boolean cantGo(int r, int c) {
if(r < 0 || c < 0 || r >= N || c >= N) return true;
return false;
}
public static void input() throws Exception {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
StringTokenizer st = new StringTokenizer(br.readLine());
N = Integer.parseInt(st.nextToken());
M = Integer.parseInt(st.nextToken());
map = new int[N][N];
visit = new boolean[M][N][N];
for(int i = 0; i < N; i++) {
st = new StringTokenizer(br.readLine());
for(int j = 0; j < N; j++) {
map[i][j] = Integer.parseInt(st.nextToken());
}
}
for(int i = 0; i < M; i++) {
st = new StringTokenizer(br.readLine());
int r = Integer.parseInt(st.nextToken()) - 1;
int c = Integer.parseInt(st.nextToken()) - 1;
friends.add(new int[] {r, c, map[r][c], 0}); //r, c, 시작값, 시간(bfs에서 사용)
}
}
}
'알고리즘 > 소프티어' 카테고리의 다른 글
[소프티어] 나무 섭지 LV.3 (1) | 2024.06.30 |
---|