728x90
SW Expert [모의 SW 역량테스트] 2105번 디저트 카페 :
https://swexpertacademy.com/main/code/problem/problemDetail.do?contestProbId=AV5VwAr6APYDFAWu
대각선 방향으로 디저트 카페를 탐색하는 문제이다.
특이한 조건이 있다면, 대각선 방향으로 이동하여 사각형 모양을 그리면서 출발할 카페로 돌아와야 한다는 점이다.
이러한 조건으로 탐색하는 범위는 절반으로 줄일 수 있다.
위와 같은 탐색 경로가 있다면, 절반으로 나눠서 위쪽 부분만 구한다면 아래쪽의 경로는 자동으로 나오게 된다.
이번 문제에서는 대각선으로 움직이기 때문에 dx, dy를 평소랑 다르게 지정해주었다. ↗, ↘, ↙, ↖ 의 순서로 0, 1, 2, 3으로 지정해주었다.
dfs로 탐색을 했고, 변수로는 해당 인덱스 x, y와 디저트 종류가 들어 있는 set과 움직인 방향을 저장한 path가 있다.
path의 마지막 저장된 변수가 2라면, ↙ 방향으로 움직이는 것으로 판단하여 절반의 탐색이 종료한다.
절반의 탐색이 끝나면 지금까지 움직인 path 정보를 가지고 나머지 경로를 찾는다.
예를 들어 (x, y) = (2, 3)이고 path가 [0, 0, 1, 2]라면,
뒤에 path 변수에 2씩 더 한 값을 dir로 하여 다음 위치 nx, ny를 찾아준다.
path의 뒤에 2개는 무시하게 되므로 (3,2)와 (4,1) 위치를 탐색하여 set에 추가해준다.
코드
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.StringTokenizer;
public class Main {
private static int n, answer;
private static int[][] map;
private static int[] dx = {-1, 1, 1, -1};
private static int[] dy = {1, 1, -1, -1};
public static void main(String[] args) throws Exception {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
StringTokenizer st;
int T = Integer.parseInt(br.readLine());
for (int t = 1; t <= T; t++) {
n = Integer.parseInt(br.readLine());
map = new int[n][n];
answer = -1;
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());
}
}
solution();
System.out.println("#" + t + " " + answer);
}
}
private static void solution() {
HashSet<Integer> set = new HashSet<>();
ArrayList<Integer> path = new ArrayList<>();
for (int i = 1; i < n - 1; i++) {
for (int j = 0; j < n - 2; j++) {
set.add(map[i][j]);
path.add(0);
dfs(i, j, set, path);
set.clear();
path.clear();
}
}
}
private static void dfs(int x, int y, HashSet<Integer> set, ArrayList<Integer> path) {
int dir = path.get(path.size() - 1);
if (dir == 2) {
int count = addRest(x, y, set, path);
if (answer < count) answer = count;
return;
}
int nx = x + dx[dir], ny = y + dy[dir];
if (!isValid(nx, ny) || set.contains(map[nx][ny])) return;
HashSet<Integer> tSet = new HashSet<>(); // set 복사
tSet.addAll(set);
tSet.add(map[nx][ny]); // 다음 디저트 추가
ArrayList<Integer> tPath = new ArrayList<>(); // path 복사
tPath.addAll(path);
tPath.add(dir);
dfs(nx, ny, tSet, tPath); // 같은 방향 추가로 탐색
tPath.remove(tPath.size() - 1);
tPath.add(dir + 1);
dfs(nx, ny, tSet, tPath); // 방향 꺾어서 탐색
}
private static int addRest(int x, int y, HashSet<Integer> set, ArrayList<Integer> path) {
int nx = x, ny = y, dir;
for (int i = 0; i < path.size() - 2; i++) {
dir = path.get(i) + 2;
nx = nx + dx[dir];
ny = ny + dy[dir];
if (!isValid(nx, ny) || set.contains(map[nx][ny])) return -1;
set.add(map[nx][ny]);
}
return set.size();
}
private static boolean isValid(int x, int y) {
if (x < 0 || y < 0 || x >= n || y >= n) return false;
return true;
}
}
728x90
'Algorithm > SW Expert Academy' 카테고리의 다른 글
[SW Expert] [모의 SW 역량테스트] 4013번 특이한 자석 (Java) (0) | 2020.02.17 |
---|---|
[SW Expert] [모의 SW 역량테스트] 2112번 보호 필름 (Java) (0) | 2020.02.17 |
[SW Expert] [모의 SW 역량테스트] 2117번 홈 방범 서비스 (Java) (0) | 2020.02.16 |
[SW Expert] [모의 SW 역량테스트] 1949번 등산로 조성 (Java) (0) | 2020.02.16 |
[SW Expert] [모의 SW 역량테스트] 1953번 탈주범 검거 (Java) (0) | 2020.02.14 |