Skip to content
This repository was archived by the owner on Mar 18, 2024. It is now read-only.

[2023-08-07] sumin #94 #102

Merged
merged 1 commit into from
Aug 7, 2023
Merged

[2023-08-07] sumin #94 #102

merged 1 commit into from
Aug 7, 2023

Conversation

ksumini
Copy link
Contributor

@ksumini ksumini commented Aug 6, 2023

PR Summary

풀이시간: 10분

<제한사항>

  • 각 던전은 하루에 한 번만 탐험이 가능하다 -> 하루 동안 최대한 많이 탐험하려고 한다.
  • dungeons의 길이(즉, 던전의 개수)는 1 이상 8 이하이다.

<solution>

  • dungeons의 길이가 최대 8이기 때문에, 모든 경우의 수를 확인하는 브루트 포스(완전탐색)으로 문제 풀이가 가능하다.
  • 얼핏보면 그리디로 접근할 수 있나? 생각할 수 있지만, n(dungeons의 길이)이 매우 작고 몇 가지 그리디를 생각해봐도 반례가 무수히 많이 존재하기 때문에 그리디로 풀 수 없다.
    • 1) 매번 가장 적은 소모 피로도를 가진 던전부터 탐험 -> k = 80, dungeons=[[30, 10], [80, 20], [60, 30]] -> 1개(정답은 3개)
    • 2) 매번 가장 큰 최소 필요 피로도를 가진 던전부터 탐험 -> 문제의 예시와 동일
      기타 등등

<시간복잡도>
dungeons의 길이는 최대 8로 연산횟수는 최대 8! = 40320으로 시간 내에 충분히 통과가 가능하다.

dungeons의 모든 순열(permutations)을 만들면 최대 8! = 40320이며
각 순열마다, 던전들을 반복하며 now와 cnt 값을 계산하기 때문에 모든 순열에 대해 O(n)이 걸린다.

따라서, 전체적으로 솔루션의 시간 복잡도는 O(n * n!)로 최대 8 * 8! = 322560의 연산횟수를 갖지만 충분히 시간 내에 통과 가능하다.

<번외>
이 문제는 어떤 던전부터 방문할 것인지 '순서'가 중요하고 순열을 임의의 수열을 다른 '순서'로 섞는 연산이기 때문에 순열로 풀이가 가능하다.
마찬가지로 permuations 라이브러리를 사용하지 않고, next_permutation을 구현해서 풀 수도 재귀를 이용해 풀 수도 있다.
+두 가지 풀이도 각각 추가했음

ISSUE NUMBER

@ksumini ksumini self-assigned this Aug 6, 2023
@ksumini ksumini linked an issue Aug 6, 2023 that may be closed by this pull request
Copy link
Contributor

@zsmalla zsmalla left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

next permutation이라는 알고리즘을 배워갈 수 있어서 너무너무 좋았습니다! 깔끔하면서도 효율적인 백트래킹까지 완벽하게 구현해내셨네요! 저도 담부터는 구현 가능한 알고리즘을 모두 시도해보는 모습을 보여드리도록 하겠습니다! 고생하셨습니다!

from typing import List

# 다음 순열로 풀기
def next_permutation(a): # 순열 a를 계속 변경
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

next permutation 알고리즘에 대해서 처음으로 알아갑니다! 이번 문제와 같이 특정 개수의 순열을 뽑아낼 필요가 없는 문제에 대해서는 재귀로 구현한 순열보다 훨씬 효율적으로 해결할 수 있는 알고리즘인 것 같아요!

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

저도 Next Permutation이라는 알고리즘을 처음 들어 개념을 다시 보고 왔습니다. 처음보는 개념이라 완전한 이해는 아니지만 이런 방법이 있다는 걸 깨달을 수 있어 좋았습니다! 감사합니다 수민님! 👍

a[i-1], a[j] = a[j], a[i-1]

j = len(a)-1
# 4. A[i]부터 순열을 뒤집는다.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

알고리즘을 보고 매번 정렬을 거치는 과정이 오히려 연산량 측면에서 부담이지 않을까 싶었는데, 이미 내림차순 정렬되어있기 때문에 대칭되는 부분만 바꿔주면 되어서 연산량 측면에서 괜찮은 것이라고 이해해도 될까요??

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

넵! 이 부분은 O(N)이 걸려요!! 매번 정렬 알고리즘으로 정렬한다면 O(NlogN)이 걸리겠지만..!

예를 들어, 다음과 같은 순열이 있을 때

순열: 7 2 4 6 5 3 1
A[i]부터 끝까지 while문을 통해 순열을 뒤집으면 최악의 경우 O(N)이 걸리겠죠?!
순열: 7 2 4 1 3 5 6

그래서 결과적으로 수열의 크기가 N이라고 할 때,

  1. i를 찾는다: O(N)
  2. j를 찾는다: O(N)
  3. i-1, j를 swap: O(1)
  4. i ~ N까지 순열을 뒤집는다 : O(N)
    이기 때문에 다음 순열을 구하는데 걸리는 시간복잡도는 **O(N)**이 걸려요~!

now -= use
if cnt > answer:
answer = cnt
if not next_permutation(a): # 다음 순열이 없다면 종료
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

캬 자연스럽게 실행되는 로직까지 이쁜 코드 같아요!

for permu in permutations(dungeons):
now = k # 현재 피로도 초기화
cnt = 0 # 유저가 탐험할 수 있는 던전의 수 초기화
for need, use in permu: # 모든 경우의 수
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

정확히 방식이 동일해서 보기 편했습니다.

for i in range(n):
if k >= dungeons[i][0] and not visited[i]:
visited[i] = True # 방문처리
go(k - dungeons[i][1], cnt+1, dungeons) # 현재 피로도 - 소모 피로도
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

와 백트래킹으로 풀이를 할 수 있다는게 정말 놀랍네요 공부가 더욱 필요하다는 것을 절실히 느끼게 되었습니다. 감사합니다 수민님! 👍

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

사실 완탐은 결국 재귀로도 풀 수 있어야 하는 거 같기는해요.. ㅎㅎ

from typing import List

# 다음 순열로 풀기
def next_permutation(a): # 순열 a를 계속 변경
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

저도 Next Permutation이라는 알고리즘을 처음 들어 개념을 다시 보고 왔습니다. 처음보는 개념이라 완전한 이해는 아니지만 이런 방법이 있다는 걸 깨달을 수 있어 좋았습니다! 감사합니다 수민님! 👍

@ksumini ksumini merged commit f01cfbf into main Aug 7, 2023
@ksumini ksumini deleted the sumin-#94 branch August 7, 2023 09:05
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

[Programmers] 피로도
3 participants