Notice
Recent Posts
Recent Comments
- Today
- Total
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | 6 | 7 |
8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 | 16 | 17 | 18 | 19 | 20 | 21 |
22 | 23 | 24 | 25 | 26 | 27 | 28 |
29 | 30 | 31 |
Tags
- kotiln
- 비트마스킹
- 삼성파우치
- 투포인터
- 알고리즘
- nullalble
- 안드로이드#코틀린#디자인패턴#싱글턴패턴#개발#앱개발
- 싸피
- 안드로이드
- ssafy서울
- tomtoc
- 등산로조성
- bitmasking
- MVVM
- 탐탁삼성파우치
- lateinit
- 코틀린
- DataBinding
- 삼성청년sw아카데미
- Higher-Order
- #충무로맛집#골목식당#스테이크#
- Kotlin
- 코딩테스트
- 탐탁노트북파우치
- Android
- 삼성역량테스트
- 아키텍처패턴
- 백준
- Java
- 자바
Archives
공상하는 개발자
[알고리즘/JAVA] SWEA 1949 등산로 조성 (BFS,DFS) 본문
반응형
모의 SW 역량테스트를 준비하면서 등산로 조성이라는 문제를 접하게 되었다..
문제 링크는
와 같다.
초기 해결 방안
-> 처음 이 문제를 읽고 BFS로 풀어야겠다는 생각을 했다. 그 이유는 아직 DFS는 익숙하지 않고, BFS의 문제를 많이 접해봤기 때문이다.
이 문제는 BFS + 완전 탐색이라고 생각하였고 문제를 풀었다.
코드 (BFS + 완전탐색)
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.Queue;
import java.util.StringTokenizer;
public class Solution {
static int[][] search = { { 1, 0 }, { -1, 0 }, { 0, 1 }, { 0, -1 } };
static int N, K, MAX = Integer.MIN_VALUE;
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
int T = Integer.parseInt(br.readLine());
for (int tc = 1; tc <= T; tc++) {
MAX = Integer.MIN_VALUE;
StringTokenizer token = new StringTokenizer(br.readLine());
N = Integer.parseInt(token.nextToken());
K = Integer.parseInt(token.nextToken());
int[][] arr = new int[N][N];
int max = 0;
for (int r = 0; r < N; r++) {
token = new StringTokenizer(br.readLine());
for (int c = 0; c < N; c++) {
arr[r][c] = Integer.parseInt(token.nextToken());
if (max < arr[r][c]) {
max = arr[r][c];
}
}
}
List<Point> list = new ArrayList<>();
for (int r = 0; r < N; r++) {
for (int c = 0; c < N; c++) {
if (max == arr[r][c]) {
list.add(new Point(r, c));
}
}
}
for (int k = 0; k <= K; k++) {
for (int r = 0; r < N; r++) {
for (int c = 0; c < N; c++) {
if (arr[r][c] - k < 0) {
continue;
} else {
arr[r][c] -= k;
}
for (int i = 0; i < list.size(); i++) {
bfsQueue(list.get(i).r, list.get(i).c, arr);
}
arr[r][c] += k;
}
}
}
System.out.println("#" + tc + " " + MAX);
}
}
static void bfsQueue(int r, int c, int[][] copy) {
Queue<Point> queue = new LinkedList<>();
queue.offer(new Point(r, c));
int time = 0;
while (!queue.isEmpty()) {
int size = queue.size();
time++;
for (int i = 0; i < size; i++) {
Point top = queue.poll();
for (int s = 0; s < search.length; s++) {
int nr = top.r + search[s][0];
int nc = top.c + search[s][1];
if (isIn(nr, nc) && copy[top.r][top.c] > copy[nr][nc]) {
queue.offer(new Point(nr, nc));
}
}
}
}
if (MAX < time) {
MAX = time;
}
}
static boolean isIn(int r, int c) {
return r >= 0 && c >= 0 && r < N && c < N;
}
static class Point {
int r, c;
public Point(int r, int c) {
super();
this.r = r;
this.c = c;
}
@Override
public String toString() {
return "Point [r=" + r + ", c=" + c + "]";
}
}
}
코드 설명
- 높은 봉우리에서 시작한다고 했으니까 리스트를 만들어서 높은 봉우리의 점들을 추가해주었다.
- 한 곳을 정해서 최대 깊이 K까지 지형을 깎을 수 있다고 했으니까 모든 점에서 0부터 K까지 깎는 완전 탐색을 한다. 그 안 로직에서 BFS를 실행시켜준다.
- BFS는 방문처리를 하지 않고, 배열 범위를 벗어나지 않고, 지형이 낮아지는 쪽이면 깊이 탐색을 실행시켰다. 그리고 size를 통해 실행 횟수를 조절해주었다. 한번 실행할 때마다 time을 늘려주고, time의 최댓값을 답으로 출력하였다.
결과
결과 피드백
BFS를 통해 되는 점들을 모두 Queue에 집어넣다 보니 메모리가 많이 나온 듯하다.
그래서 이번에는 DFS를 이용해서 이문제를 풀어보려고 하였다.
수정 코드 (DFS + 완전 탐색)
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;
import java.util.StringTokenizer;
public class Solution {
static int[][] search = { { 1, 0 }, { -1, 0 }, { 0, 1 }, { 0, -1 } };
static int N, K, MAX = Integer.MIN_VALUE;
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
int T = Integer.parseInt(br.readLine());
for (int tc = 1; tc <= T; tc++) {
MAX = Integer.MIN_VALUE;
StringTokenizer token = new StringTokenizer(br.readLine());
N = Integer.parseInt(token.nextToken());
K = Integer.parseInt(token.nextToken());
int[][] arr = new int[N][N];
int max = 0;
for (int r = 0; r < N; r++) {
token = new StringTokenizer(br.readLine());
for (int c = 0; c < N; c++) {
arr[r][c] = Integer.parseInt(token.nextToken());
if (max < arr[r][c]) {
max = arr[r][c];
}
}
}
List<Point> list = new ArrayList<>();
for (int r = 0; r < N; r++) {
for (int c = 0; c < N; c++) {
if (max == arr[r][c]) {
list.add(new Point(r, c));
}
}
}
for (int k = 0; k <= K; k++) {
for (int r = 0; r < N; r++) {
for (int c = 0; c < N; c++) {
if (arr[r][c] - k < 0) {
continue;
} else {
arr[r][c] -= k;
}
for (int i = 0; i < list.size(); i++) {
dfs(list.get(i).r, list.get(i).c, 1, arr);
}
arr[r][c] += k;
}
}
}
System.out.println("#" + tc + " " + MAX);
}
}
static void dfs(int r, int c, int cnt, int[][] copy) {
for (int s = 0; s < search.length; s++) {
int nr = r + search[s][0];
int nc = c + search[s][1];
if (isIn(nr, nc) && copy[r][c] > copy[nr][nc]) {
dfs(nr, nc, cnt + 1, copy);
}
}
if (MAX < cnt) {
MAX = cnt;
}
}
static boolean isIn(int r, int c) {
return r >= 0 && c >= 0 && r < N && c < N;
}
static class Point {
int r, c;
public Point(int r, int c) {
super();
this.r = r;
this.c = c;
}
}
}
코드 변경 사항
-> DFS를 재귀로 구현하여 cnt값을 늘려주었다. 조건에 만족하게 된다면 계속해서 cnt값을 늘려주었고, cnt값 중 최댓값을 값으로 출력하였다.
결과
결론
위 문제는 DFS or BFS와 백트래킹을 이용해서 푸는 문제였다. 하나만 깎는 조건이 까다롭기 때문에 완전 탐색을 통해 푸는 것이 해답이다.
반응형
'개발 > 알고리즘' 카테고리의 다른 글
[알고리즘] 비트마스크(BitMask) 스킬 숙련하기(feat. 백준 1194 달이 차오른다, 가자.) (0) | 2020.05.17 |
---|---|
[알고리즘/JAVA] 투포인터 알고리즘 (1) | 2020.05.10 |
[알고리즘/자바] 다익스트라 알고리즘 (Dijkstra Algorithm) (1) | 2020.04.26 |
[코딩테스트 후기] 2020 라인 코딩테스트 후기(문제 해설X,찐 후기) (0) | 2020.04.06 |
[알고리즘/자바] 조합, 순열, 중복조합, 중복순열 (0) | 2020.03.14 |
Comments