//////
Search
📃

22년 1월 4주차 회고록 (스터디 자랑)

회의 날짜: 2022/01/26
회의 장소: discord 라운지
참석자: 김솔배, 구연지, 안지영, 김재근

[회고 사진]

[문제]

[이번 스터디 공부한 내용]

 김솔배

두 문제 전부 문제를 보자마자 BFS와 DFS로 풀어야 겠다는 생각이 들었습니다.
적록색약같은 경우는 BFS를 통해 같은 알파벳을 찾아내고 숫자 카운트를 올려야 한다고 생각했고
타켓넘버같은경우는 DFS 를 통해 숫자를 하나씩 더하거나 빼가면서 모든 경우의 수를 계산하면 된다고 생각했습니다.

적록색약

package week16.적록색약; import java.util.*; public class Main { private static boolean[][] isUsed; private static char[][] drugs; static int[] dX = new int[]{1, 0, -1, 0}; static int[] dY = new int[]{0, 1, 0, -1}; static int n; public static void main(String[] args) { Scanner sc = new Scanner(System.in); n = sc.nextInt(); drugs = new char[n + 1][n + 1]; isUsed = new boolean[n + 1][n + 1]; for (int i = 0; i < n; i++) { String s = sc.next(); for (int j = 0; j < n; j++) { drugs[i][j] = s.charAt(j); } } //구역을 확인하기 int answer1 = 0; for (int i = 0; i < n; i++) { for (int j = 0; j < n; j++) { if (!isUsed[i][j]) { bfs(i, j, drugs[i][j]); answer1++; } } } isUsed = new boolean[n + 1][n + 1]; for (int i = 0; i < n; i++) { for (int j = 0; j < n; j++) { if (!isUsed[i][j]) { if (drugs[i][j] == 'R') drugs[i][j] = 'G'; } } } //구역을 확인하기 int answer2 = 0; for (int i = 0; i < n; i++) { for (int j = 0; j < n; j++) { if (!isUsed[i][j]) { bfs(i, j, drugs[i][j]); answer2++; } } } System.out.println(answer1 + " " + answer2); } private static void bfs(int x, int y, char target) { Queue<int[]> q = new LinkedList<>(); q.add(new int[]{x, y}); isUsed[x][y] = true; while (!q.isEmpty()) { int[] xy = q.poll(); int currX = xy[0]; int currY = xy[1]; for (int i = 0; i < 4; i++) { int nX = currX + dX[i]; int nY = currY + dY[i]; if (nX < 0 && nX <= n || nY < 0 && nY <= n) continue; //OutOfArraysIndex 체크 if (!isUsed[nX][nY] && drugs[nX][nY] == target) { // 다음이 방문하지 않았고 문자가 같으면 isUsed[nX][nY] = true; q.add(new int[]{nX, nY}); } } } } }
Java
복사

타겟넘버

package week16.타겟넘버; import java.util.Stack; public class Solution { static int answer; public int solution(int[] numbers, int target) { dfs(numbers, target, 0, 0); return answer; } private void dfs(int[] numbers, int target, int depth, int sum) { if (depth == numbers.length) { if (sum == target) answer++; } else { dfs(numbers, target, depth + 1, sum + numbers[depth]); dfs(numbers, target, depth + 1, sum - numbers[depth]); } } public static void main(String[] args) { int[] numbers = {1,1,1,1,1}; int target = 3; Solution solution = new Solution(); int solution1 = solution.solution(numbers, target); System.out.println(solution1); } }
JavaScript
복사

 구연지

타겟넘버

숫자가 20개 이하라서 가능한 경우의 수가 최대 2^20 → 1024*1024 = 약 105만이라서 그냥 모든 경우의 수에 대해서 iter를 돌리는 것을 택했다.
import numpy as np def solution(numbers, target): def find_target(x): return x == target bef_cal = [0] for iter in range(len(numbers)): aft_cal = [0]*(2*len(bef_cal)) for bef_num_iter in range(len(bef_cal)): aft_cal[bef_num_iter*2] = bef_cal[bef_num_iter] -numbers[iter] aft_cal[(bef_num_iter*2 +1)] =bef_cal[bef_num_iter] + numbers[iter] bef_cal = aft_cal # print(bef_cal) # print(np.where(np.array(bef_cal) == target)[0]) return len(np.where(np.array(bef_cal) == target)[0])
Python
복사

 안지영

백준 10026 - 적록색약

이 문제는 하나의 그룹과 다른 그룹을 나누는게 힘들었다. 어떻게 접근해야할 지 하다가 BFS를 선택했는데, 지금까지 문제들은 한번의 BFS를 돌면 문제가 해결되는 방향이라 이렇게 모든 grid를 돌면서 조건에 맞으면 그때마다 BFS를 돈다는 생각 자체를 못해봤던 것 같다. 그리고 이 문제는 DFS로도 풀 수 있을 것 같다.
그리고 꼭! BFS로 할 때는 visited을 표시하는 위치에 주의하자!! 별로 중요하지 않은 상관없는 부분이라 생각했는데 이번에 이것으로 인해 시간과의 여부가 갈렸다! visited는 이웃 노드를 큐에 넣는 과정과 동시에 진행한다!
from collections import deque dx = [0,1,0,-1] dy = [1,0,-1,0] def num_regions(i, j, N, grid, visited): queue = deque() group_color = grid[i][j] queue.append((i,j)) visited[i][j] = 1 while queue: x, y = queue.popleft() for i in range(len(dx)): tmp_x = x + dx[i] tmp_y = y + dy[i] if tmp_x < 0 or tmp_x >= N or tmp_y < 0 or tmp_y >= N: continue if visited[tmp_x][tmp_y] or grid[tmp_x][tmp_y] != group_color: continue visited[tmp_x][tmp_y] = 1 queue.append((tmp_x, tmp_y)) return 1 N = int(input()) grid = [input() for _ in range(N)] # 보통 사람 visited = [[0] * N for _ in range(N)] general_count = 0 for i in range(N): for j in range(N): if not visited[i][j]: general_count += num_regions(i, j, N, grid, visited) # 적록 색맹인 사람 for i in range(N): grid[i]=grid[i].replace("G","R") visited = [[0] * N for _ in range(N)] daltonism_count = 0 for i in range(N): for j in range(N): if not visited[i][j]: daltonism_count += num_regions(i, j, N, grid, visited) print(general_count, daltonism_count)
Java
복사

프로그래머스 - 타겟 넘버

이 문제는 dfs로 풀어야겠다는 생각을 했는데, 항상 드는 생각이지만 저렇게 두가지 상황에 대해서 재귀 호출하는 것이 생소하다. 그래도 반복하다 보니 어느 정도 틀이 잡히는 것 같다.
answer=0 def solution(numbers, target): def dfs(sum_,indx): global answer if(indx==len(numbers)): if(sum_==target): answer = answer+ 1 return dfs(sum_+numbers[indx],indx+1) dfs(sum_-numbers[indx],indx+1) dfs(0,0) return answer
Java
복사

 김재근

적록색약

import sys sys.setrecursionlimit(int(1e6)) def dfs(x,y,mode=0): if mode == 0: col = graph[x][y] visited[x][y] = True for i in range(4): nx = x +dx[i] ny = y +dy[i] if nx < 0 or nx >=n or ny < 0 or ny >= n: continue if visited[nx][ny] or graph[nx][ny]!=col: continue dfs(nx,ny,mode) # 적록 색약인 경우 else: col = graph[x][y] visited2[x][y] = True for i in range(4): nx = x +dx[i] ny = y +dy[i] if nx < 0 or nx >= n or ny < 0 or ny >= n: continue if visited2[nx][ny]: continue if col == 'R' or col == 'G': if graph[nx][ny] == 'R' or graph[nx][ny] == 'G': dfs(nx,ny,mode) else: if graph[nx][ny] != col: continue dfs(nx,ny,mode) n = int(input()) graph = [] for _ in range(n): graph.append(list(input())) visited = [ [False for _ in range(n)] for _ in range(n)] visited2 = [ [False for _ in range(n)] for _ in range(n)] count1, count2 = 0, 0 dx, dy = [0,0,-1,1], [-1,1,0,0] for i in range(n): for j in range(n): if not visited[i][j]: dfs(i,j) count1+=1 if not visited2[i][j]: dfs(i,j,1) count2+=1 print(count1,count2)
Python
복사

 [어려웠던 부분]

 김솔배
DFS와 BFS 모두 언제 사용해야할지 이제 감이 잡힌거 같습니다. 하지만 문제의 조건마다 사용하는 법을 적용시키기가 아직 어려웠던거 같습니다. 그래서 더 정확히 DFS와 BFS의 작동원리를 알아봐야겠다고 생각했습니다
Plain Text
복사
 구연지
적록 색약의 경우 pccp 시험에서 접한 적이 있는 문제와 유사해서 꼭 풀어보고 싶었는데 (인접한 색깔의 경우 같은 구역으로 간주해서 색깔을 칠하면 최종으로 몇개의 구역으로 나뉘는지) 같은 색깔이지만 다른 위치에 있는 경우 어떻게 처리해야하는지 까다로워서 풀지 못했다. DFS를 이용하면 된다고 하니 그 방법을 이용해서 다시 풀어봐야겠다.
Plain Text
복사
 안지영
파이썬에 대한 이해가 부족하다는 생각이 든 것이, 어떤 변수의 값을 변경하고 싶을 때 함수에 매개변수로 넘겨줘야 하는 지, 그렇게 하지 않아도 호출해서 변경이 될 수 있는지가 늘 헷갈린다. 함수 밖의 변수는 함수 내에서 호출이 안된다고 알고 있었는데 그렇지 않은 경우도 있는 것 같다. 중요한 문제이니 공부를 좀 해봐야겠다.
Plain Text
복사
 김재근
bfs / dfs 로 접근해서 풀어야겠다는 생각이 들었는데 정작 둘 중 어떤 방식으로 풀어야 조금 더 좋은 방법인지 아직 잘 모르겠습니다.
Plain Text
복사

 [금주의 꿀팁 & 인사이트!]

 김솔배
DFS와 BFS는 공식이 있는것 같으니 구조를 외워놓고 사용하면 좋겠다고 생각했습니다. 다만 사용할때 문제마다 적용하는방법이 다를 수 있으니 내부구조를 잘 파악해두어야 한다고 생각했습니다.
Plain Text
복사
 구연지
이번주는 꿀팁은 없는 것 같다. 그냥 습관적으로 시간 복잡도를 계산하는 것이 반복문을 바로 돌릴지 다른 방법을 생각할지에 도움을 주는 것이 아닌가 싶은 생각은 든다.
Plain Text
복사
 안지영
물론 최종적으로 사용하진 않았지만 PriorityQueue를 사용하는 연습을 해보았다.
Plain Text
복사
 김재근
조금 구글링을 해보니 파이썬으로 푼 대부분의 사람들이 deque라는 collections의 라이브러리를 이용해서 푸는데 collections를 잘 활용해봐야겠습니다.
Plain Text
복사

 [금주의 느낀 점]

 김솔배
이제 문제를 보면 어떻게 접근해야할지 아는정도는 된거같으니 좀 더 꾸준히 연습해서 더 효율적으로 깔끔하게 짜는 방법을 연구해 보아야 할 것 같습니다.
Plain Text
복사
 구연지
저번 주처럼 BFS나 DFS를 이용해서 더더 많은 문제를 풀어봐야할 것 같다는 생각을 했다.
Plain Text
복사
 안지영
알고리즘에 시간을 더 투자해야 할 것 같다. 요즘 프로젝트에 정신이 팔려서 알고리즘을 조금 대충 했던 것 같은데 그럴 때가 아닌 것 같다.
Plain Text
복사
 김재근
일주일에 두 문제를 풀기로 약속했는데 항상 한문제 밖에 못 푸는 것 같다 시간을 조금 더 투자해야겠습니다 ... ㅠ
Plain Text
복사