최's 먹공로그
SWEA1767_[SW Test 샘플문제] 프로세서 연결하기 본문
https://swexpertacademy.com/main/code/problem/problemDetail.do?contestProbId=AV4suNtaXFEDFAUf
문제정리
1. 1개의 cell에는 1개의 core 혹은 1개의 전선이 올 수 있다.
2. 맥시노스의 가장 자리에는 전원이 흐르고 있다.
3. core와 전원을 연결하는 전선은 직선으로만 설치가 가능하며, 전선은 교차해서는 안 된다.
4. 맥시노스의 가장자리에 위치한 core는 이미 전원이 연결된 것으로 간주한다.
5. 최대한 많은 core에 전원을 연결하였을 경우, 전선 길이의 합을 구하고자 한다.
단, 여러 방법이 있을 경우, 전선 길이의 합이 최소가 되는 값을 구하라.
문제issue
1. 중복순열로 연결해야하는 core당 4방향을 모두 살펴보면 최악의 경우 4PI12 라서 시간초과가 발생한다.
2. dfs 재귀를 이용
해결흐름
1. 연결해야 하는 core의 위치를 list에 저장한다.
2. dfs
(1) 종료조건 : list를 살펴보는 인덱스가 list의 크기와 같아지면 list에 있는 모든 core를 살펴봤다는 의미이다.
(2) 가지고 다닐 값 : core가 있는 list , list에서 core를 꺼낼 인덱스 , 몇 개의 core를 연결했는가? , 몇 개의 전선?
(3) 복귀 시켜야 할 값 : map
(4) 재귀를 도는 경우 : 뽑은 core가 한 방향으로 전원가 연결 가능할 때
아닌 경우 : 이 문제는 core를 전원에 연결 못 하더라도 재귀를 돌아야 한다. 다만 현재까지 연결한 core의 개수와 전선의 개수를 갱신 하지 않는다.
3. check()에서는 core 한 개와 방향을 받아서 전원과 연결이 가능한지 검사하고 가능하면 2(전선을 의미)로 맵핑한다.
이때, 전선의 개수를 증가시켜서 끝난후 다음 재귀를 돌때 더해준다.
DFS문제issue
DFS 재귀를 이용하여 문제를 풀기 전에 꼭 생각!!
1. 재귀의 종료조건
2. 함수와 함께 가지고 다닐 값
3. return 후에 원상복귀 시켜야 할 값
4. 재귀를 도는 경우와 아닌 경우
소스코드
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 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 | 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 class pair { int r; int c; public pair(int r, int c) { super(); this.r = r; this.c = c; } } private static int max_core; private static int min_line; private static int N; private static int[][] map; public static void main(String[] args) throws Exception { // input BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); int test_case = Integer.parseInt(br.readLine().trim()); for (int tc = 1; tc <= test_case; tc++) { N = Integer.parseInt(br.readLine().trim()); map = new int[N][N]; List<pair> core_list = new ArrayList<pair>(); for (int i = 0; i < N; i++) { StringTokenizer st = new StringTokenizer(br.readLine().trim()); for (int j = 0; j < N; j++) { int number = Integer.parseInt(st.nextToken()); map[i][j] = number; if (number == 1 && i > 0 && i < N - 1 && j > 0 && j < N - 1) { core_list.add(new pair(i, j)); } } } max_core = Integer.MIN_VALUE; min_line = Integer.MAX_VALUE; dfs(core_list, 0, 0, 0); // core담은 list , list에서 꺼낼 변수 idx , 연결한 core 개수 core_cnt , 연결한 전선 개수 line_cnt System.out.println("#" + tc + " " + min_line); } // end of tc } // end of main private static int[] dr = { -1, 0, 1, 0 }; // 상 우 하 좌 private static int[] dc = { 0, 1, 0, -1 }; // 상 우 하 좌 private static void dfs(List<pair> core_list, int idx, int core_cnt, int line_cnt) { // 종료조건 , core_list의 모든 core를 살펴보았다 if (idx == core_list.size()) { // 값 갱신 if (max_core < core_cnt) { max_core = core_cnt; min_line = line_cnt; } else if (max_core == core_cnt) { if (min_line > line_cnt) { max_core = core_cnt; min_line = line_cnt; } } return; } // core 한 개당 4방향으로 가능한지 살펴본다 pair p = core_list.get(idx); for (int i = 0; i < dc.length; i++) { int line_plus = check(p, i); // 몇번재 코어인지와 방향을 던져준다 // 해당 core가 해당 방향으로 연결이 가능하다 if (line_plus != -1) { dfs(core_list, idx + 1, core_cnt + 1, line_cnt + line_plus); // 변경했던 map을 원상복귀 시켜준다 int r = p.r; int c = p.c; int dir = i; while(true) { r += dr[dir]; c += dc[dir]; if(r >= 0 && r < N && c >= 0 && c < N) { map[r][c] = 0; } else break; } } } dfs(core_list, idx + 1, core_cnt, line_cnt); } private static int check(pair p, int dir) { int r = p.r; int c = p.c; boolean flag = false; while (true) { r += dr[dir]; c += dc[dir]; if (r >= 0 && r < N && c >= 0 && c < N) { // 전원이랑 연결이 가능하다 if ((r == 0 || r == N - 1 || c == 0 || c == N - 1) && map[r][c] == 0) { flag = true; break; } else if (map[r][c] != 0) { flag = false; break; } // 전원이랑 연결이 불가능하다 } } // 위에서 검사결과 연결이 가능하다 r = p.r; c = p.c; int line_plus = 0; if (flag) { while (true) { r += dr[dir]; c += dc[dir]; if (r >= 0 && r < N && c >= 0 && c < N) { line_plus++; map[r][c] = 2; } else break; } return line_plus; } return -1; } } // end of class | cs |
'APS' 카테고리의 다른 글
BOJ11559_Puyo Puyo (1) | 2019.09.05 |
---|---|
BOJ17136_색종이 붙이기 (0) | 2019.09.03 |
BOJ17140_이차원배열과 연산 (0) | 2019.09.01 |
BOJ16235_나무 재테크(시간제한 변경으로 다시) (0) | 2019.08.31 |
SWEA1953_[모의 SW 역량테스트] 탈주범 검거 (0) | 2019.08.29 |