-
[DP] 백준 풀이 기록 JAVA (Feat. do it 알고리즘 코딩테스트)Java/코딩테스트 2023. 4. 5. 16:13
tmi)
최근 do it 알고리즘 코딩테스트 자바 편을 보며 코테 공부를 하고 있다.
작년 8월까지 동아리 활동을 하고, 9~12월 인턴활동을 한 다음 인턴 퇴사 후 한달정도 쉬다가 토익보고 오픽보고 자소서 쓰고 취준활동을 했다. 인성검사, 코테...도 보고 면접까지 가 본 회사도 있지만 아직 취준 중인 백수..이다 ㅎㅎ
혼자서 공부하면 잘 못하는데 그래도 이 책은 열심히!! 마지막 12장을 남겨두고 거의 다 끝나간다! 그 와중에 동적계획법이 너무 어려워서 ........ 간만에 블로그도 쓸 겸, 공부한 내용 정리도 할 겸 자주 보려고 쓰는 글.. .(아무레도 인텔리제이 키는거보다 블로그 글 보는게 더 손이 자주가니까!)
솔직히 거의 책보면서 코드를 이해하는 수준이다 내 지식으로 만들려면 일단 이해먼저 해야겠지..
| chap 11 동적계획법 | 1163 | | chap 11 동적계획법 | 14501 | | chap 11 동적계획법 | 2193 | | chap 11 동적계획법 | 11726 | | chap 11 동적계획법 | 10844 | | chap 11 동적계획법 | 13398 | | chap 11 동적계획법 | 9252 | | chap 11 동적계획법 | 1915 | | chap 11 동적계획법 | 1328 | | chap 11 동적계획법 | 2342 | | chap 11 동적계획법 | 11049 | | chap 11 동적계획법 | 2098 | | chap 11 동적계획법 | 14003 |
동적계획법
- 큰 문제를 반복되는 작은 문제로 나눌 수 있으며, 작은 문제들의 결과값은 항상 같다.
- 작은 문제들은 한번씩만 계산하여 그 값을 저장해두고, 추후 재사용(메모제이션 기법)
- 재귀함수 방식으로 구현해나가는 top-down / 반복문 돌리는 bottom-up
# 1163
점화식 DP[i] = i 에서 1로 만드는데 걸리는 최소 연산 횟수
- 1을 뺀다 -> DP[i] = DP[i-1] + 1 (연산 1번 수행했으므로 더하기 1)
- 2로 나눈다 -> DP[i] = DP[i/2] + 1
- 3로 나눈다 -> DP[i] = DP[i/3] + 1
이 3가지 옵션들을 비교하며 최소 연산을 계산
DP[1] = 0; for (int i = 2; i <= n; i++) { DP[i] = DP[i-1] + 1; if (i % 3 == 0) { DP[i] = Math.min(DP[i], DP[i/3] + 1); } if (i % 2 == 0) { DP[i] = Math.min(DP[i], DP[i/2] + 1); } }
# 14501
점화식
- DP[i] : i번째 날 부터 퇴사날까지 얻을 수 있는 최대 수익
해당 일에 잡히는 상담이 퇴사 전에 끝나는 경우 진행할건지 말건지를 결정해야 한다.
1 ) 해당 날에 상담을 진행한 경우 -> 이 상담이 끝날 때까지는(time[i]동안) 다른 수익이 없다. DP[i + time[i]] + price[i]
2 ) 상담 진행하지 않은 경우 -> DP[i+1]과 동일할 것!
DP[i] = Math.max(DP[i+1], DP[i + time[i]] + price[i]);
for (int i = n; i > 0; i--) { if (time[i] + i <= n+1) { // 제시간안에 상담이 끝나는 경우 DP[i] = Math.max(DP[i+1], DP[time[i] + i] + price[i]); } else { DP[i] = DP[i+1]; } }
# 2098 외판원 순회
- 리스트 형태의 데이터를 1개의 자료형에 저장하는 방법 : bit 사용하면 된다
- 이진수로 도시의 방문 여부를 저장 (ex 1010 : 2, 4 도시 방문한거, 총 도시 4개 이런식으로 )
- 2번 도시를 추가로 방문한다 : 1 << 2하고 & 연산자
이 문제에서는 cycle여부를 파악하는걸 간과하면 안된다. 이거때문에 계속 시간초과 났었다.
처음에는 사이클이 끊겨서 출발지로 도달할 수 없는 경우와 아직 방문하지 않은 경우 둘다 Integer.MAX_VALUE값으로 해놨었다.
근데 그러면 notCycle(돌아올 수 없는 경우)도 아직 방문하지 않은 곳으로 간주되어 계속 탐색해서 시간초과가 나는 것 같다.
따라서 진짜 아직 방문 안한 도시인건지, 가봤지만 못 돌아가는 건지 구분해야할 것 같다.
📝 notCycle이 더 작은값이어야 Math.min()함수를 통해 갱신이 된다.
public static int notCycle = 1000000 * 16 + 1; public static int notVisited = notCycle * 2;
// 메인함수에서 DP배열 notVisited로 초기화하고 TSP 수행 for (int i = 0; i < n; i++) { for (int j = 0; j < 1<<n; j++) { DP[i][j] = notVisited; } } System.out.println(TSP(0, 1)); static int TSP (int c, int v) { // 모든 도시를 방문한 경우 if (v == (1 << n) - 1) { if (cityInfo[c][0] != 0) { return cityInfo[c][0]; } else { return notCycle; } } // 이미 최소 비용이 계산이 되어 있다면(notVisited가 아니라면) if (DP[c][v] != notVisited) { return DP[c][v]; } for (int i = 0; i < n; i++) { // 갈 수 있고, 아직 방문을 안 했을 경우 if (cityInfo[c][i] != 0 && (v & (1 << i)) == 0) { DP[c][v] = Math.min(DP[c][v], TSP(i, (v | (1 << i))) + cityInfo[c][i]); } } return DP[c][v]; }
'Java > 코딩테스트' 카테고리의 다른 글
백준 14503 (0) 2023.04.06 [ DFS / BFS ] 개념 및 예제 정리 (0) 2023.04.05 백준 11003(Java) (0) 2022.08.07 백준 1940, 1253, 12891(JAVA) (0) 2022.07.31 백준 11659, 11660, 2018(Java) (0) 2022.07.18