[백준] 1941번 소문난 칠공주 (자바 풀이)
- 알고리즘 문제 해결(PS)/[백준]
- 2022. 5. 9.
문제
https://www.acmicpc.net/problem/1941
풀이
이 문제는 단순히 BFS, DFS를 사용하면 해결하기 매우 힘들다. 모든 자리에서 4방향을 모두 조사하는 식으로 탐색하면 경우의 수가 너무 많아 시간 초과가 발생한다. 따라서 조합을 사용하여 해결하는 편이 좋다.
25개의 자리 중 7개를 선택하는 경우의 수는 25C7 = 480700 으로 작은 편이다.
1. 25개의 자리 중 7개를 뽑는다.
2. 해당 7개의 자리가 모두 상하좌우로 연결되어 있는지 확인한다(DFS 혹은 BFS 사용)
3. 'S'가 4개 이상 포함되는지 확인한다.
위와 같은 과정을 통해 문제를 해결할 수 있다. 이때 자리는 25개로 고정이므로 25개의 자리 중 7을 뽑는 것은 0~24의 숫자 중 7개를 뽑는 것으로 생각해도 편하다. 이렇게 1차원 숫자로 뽑은 뒤, 미리 X좌표와 Y좌표를 계산해 놓은 배열을 이용하면 편하다.
예를 들어, 13번 자리를 뽑았다고 하자. 미리 0~24의 숫자로 좌표를 계산해놓은 배열 combX[], combY[]를 이용하면,
combX[13] = 2;
combY[13] = 3;
이렇게 좌표를 구할 수 있다.
이후 일반적인 조합을 구현하는 함수를 통해 25개의 자리 중 7개를 선택했다면, bfs 탐색을 통해 자리가 모두 이어져있는지 확인한다.
이때 상하좌우 4방향을 모두 조사하면서 7개의 자리 중 하나라도 있는지 확인하는 식으로 탐색하면 된다. bfs 탐색을 하면서 'S'의 개수도 세주면 된다.
코드
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 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 | import java.util.*; public class Baekjoon_1941 { static char map[][] = new char[5][5]; static int dx[] = {-1,1,0,0}; static int dy[] = {0,0,-1,1}; static int combX[] = new int[25]; static int combY[] = new int[25]; static int ans = 0; public static void main(String[] args) { Scanner sc = new Scanner(System.in); for(int i=0; i<5; i++) { map[i] = sc.next().toCharArray(); } /* 좌표 미리 계산 */ for(int i=0; i<25; i++) { combX[i] = i % 5; combY[i] = i / 5; } combination(new int[7], 0,0,7); System.out.println(ans); } public static void combination(int[] comb, int idx, int depth, int left ) { if(left == 0) { bfs(comb); return; } if(depth == 25) return; comb[idx] = depth; combination(comb, idx+1, depth+1, left-1); // 선택한 경우 combination(comb, idx, depth+1, left); // 선택하지 않은 경우 } public static void bfs(int comb[]) { Queue<Integer> q = new LinkedList<>(); boolean visited[] = new boolean[7]; visited[0] = true; q.add(comb[0]); int cnt = 1, sCnt = 0; while(!q.isEmpty()) { int cur = q.poll(); if(map[combY[cur]][combX[cur]] == 'S') sCnt++; for(int i=0; i<4; i++) { for(int next=1; next<7; next++) { if(!visited[next] && combX[cur]+dx[i] == combX[comb[next]] && combY[cur]+dy[i] == combY[comb[next]]) { visited[next] = true; q.add(comb[next]); cnt++; } } } } /* 7개 모두 연결되어 있다면 */ if(cnt == 7) { if(sCnt >=4) { ans++; } } } } | cs |
반응형
'알고리즘 문제 해결(PS) > [백준]' 카테고리의 다른 글
[백준] 16500번 문자열 판별 (자바 풀이) (0) | 2022.05.16 |
---|---|
[백준] 1522번 문자열 교환 (자바 풀이) (0) | 2022.05.04 |
[백준] 20056번 마법사 상어와 파이어볼 (자바 풀이) (0) | 2022.05.02 |
[백준] 2210번 숫자판 점프 (자바 풀이) (0) | 2022.04.28 |
[백준] 2140번 지뢰찾기 (자바 풀이) (0) | 2022.04.05 |