Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

week18_hw0603 #132

Open
wants to merge 3 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 32 additions & 0 deletions week18/A_31927/hw0603/31927.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import sys

N = int(sys.stdin.readline())
arr = list(map(int, sys.stdin.readline().strip().split()))
result = []

"""arr[leftIdx-1] > arr[leftIdx]+x and arr[rightIdx]-x > arr[rightIdx+1] 인 x의 최댓값 k
즉.. arr[leftIdx-1] - arr[leftIdx] > x and arr[rightIdx] - arr[rightIdx+1] > x 인 x의 최댓값 k
즉... k = min(arr[leftIdx-1] - arr[leftIdx], arr[rightIdx] - arr[rightIdx+1], 1000000)
"""

for i in range(N//2):
leftIdx, rightIdx = i, N-(i+1)
if (leftIdx == 0):
arr[leftIdx] += 1000000
arr[rightIdx] -= 1000000
result.append(arr[:])
continue

k = min(arr[leftIdx-1] - arr[leftIdx], arr[rightIdx] - arr[rightIdx+1], 1000000)
arr[leftIdx] += k
arr[rightIdx] -= k

result.append(arr[:])


if (result and result[-1] != sorted(result[-1], reverse=True)):
print(-1)
sys.exit()
print(N//2)
for r in result:
print(*r, sep=' ')
9 changes: 8 additions & 1 deletion week18/A_31927/hw0603/README.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,14 @@
# Info
[Link](https://boj.kr/31927)
[31927 렬정! 렬정! 렬정!](https://boj.kr/31927)

## 💡 풀이 방법 요약
더할 수 있는 수가 충분히 크므로, `k = min(arr[leftIdx-1] - arr[leftIdx], arr[rightIdx] - arr[rightIdx+1], 1000000)` 를 더하고 뺀다.
- 루프 첫 시행에는 그냥 10^6으로 잡고 더하고 빼면 된다.

## 👀 실패 이유
리스트 복사할때 깊은복사 안함...
인덴트 잘못 맞춰서 루프 스코프 달라짐...
계산 결과 `k`가 1000000 넘어감...

## 🙂 마무리
급하게 풀지 말자.........
45 changes: 45 additions & 0 deletions week18/C_32128/hw0603/32128.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import sys

N, M, K = map(int, sys.stdin.readline().split())
S = [[None] + list(map(int, sys.stdin.readline().split())) for _ in range(M)]
operation = [list(map(int, sys.stdin.readline().split())) for _ in range(K)]
cards = [None] + list(range(1, N+1))


# 테크닉 하나 받아서 순열 사이클 분할
def decomposite(Si, N):
visited = set()
cycles = []

for i in range(1, N+1):
if (i in visited):
continue
cycle = []
cur = i
while (cur not in visited):
visited.add(cur)
cycle.append(cur)
cur = Si[cur]
cycles.append(cycle)

return cycles

def doShuffle(cards, applyCnt, cycles):
new_cards = cards[:]

for cycle in cycles:
cycleSize = len(cycle)
effectiveApplyCnt = applyCnt % cycleSize
for i in range(cycleSize):
new_cards[cycle[(i+effectiveApplyCnt) % cycleSize]] = cards[cycle[i]]

return new_cards


permutationCycles = [decomposite(Si, N) for Si in S] # 각 셔플 기술에 사이클 분할 적용
for Xi, Yi in operation:
Xi -= 1
decomposed = permutationCycles[Xi]
cards = doShuffle(cards, Yi, decomposed)

print(*cards[1:], sep=' ')
8 changes: 7 additions & 1 deletion week18/C_32128/hw0603/README.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,13 @@
# Info
[Link](https://boj.kr/32128)
[32128 셔플 기계](https://boj.kr/32128)

## 💡 풀이 방법 요약
길이 `L`의 임의의 순열은 `N(<L))`개의 사이클로 분할할 수 있다.
`visited` 처리를 활용하여 주어진 순열들을 모두 분할해 두고, 해당 순열을 사용하여 셔플할 때 사이클을 참조하여 나머지 연산을 통해 중복 계산을 줄여야 한다.


## 👀 실패 이유
쌩 구현으로 풀고 TLE 맞을거 같았지만 일단 제출했는데 역시 TLE를 받았다.

## 🙂 마무리
처음 보는 유형이네요.. 흥미로웠습니다.
32 changes: 32 additions & 0 deletions week18/D_32203/hw0603/32203.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import sys

N, M = map(int, sys.stdin.readline().strip().split())
parent = list(range(N+1))
c = [None] + list(map(int, sys.stdin.readline().strip().split()))
people = [None] + [(1, 0) if c[i] % 2 else (0, 1) for i in range(1, N+1)] # 각 집합안에 남자/여자 수

def union(n1, n2) -> int:
result = 0

n1p, n2p = find(n1), find(n2) # 각자 부모 찾고
result += people[n1p][0] * people[n2p][1] # n1그룹 남자 x n2그룹 여자 매칭
result += people[n1p][1] * people[n2p][0] # n1그룹 여자 x n2그룹 남자 매칭

# 병합
ch, pa = max(n1p, n2p), min(n1p, n2p)
parent[ch] = find(pa) # 부모 찾아서 바로밑에 갖다 붙임
people[pa] = (people[pa][0]+people[ch][0], people[pa][1]+people[ch][1]) # 부모는 자식정보를 포함

return result

def find(node):
if (parent[node] != node):
parent[node] = find(parent[node])
return parent[node]

ans = 0 # 남녀 쌍 개수
for _ in range(M):
a, b = map(int, sys.stdin.readline().strip().split())
if (find(a) != find(b)):
ans += union(a, b)
print(ans)
7 changes: 6 additions & 1 deletion week18/D_32203/hw0603/README.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,12 @@
# Info
[Link](https://boj.kr/32203)
[32203 연락](https://boj.kr/32203)

## 💡 풀이 방법 요약
Union Find 응용
Union 시 항상 자신이 속하는 그룹 내의 남x여 를 모두 매칭시킨 후 모든 경우의 수를 반환한다.
이를 수행하기 위해서 Union 연산 수행 시 부모 집합이 되는 집합에는 자식 집합이 되는 집합의 정보를 누적해 줘야 한다.

## 👀 실패 이유

## 🙂 마무리
처음에 그냥 `isMale` 같은 `bool` 형으로 성별정보를 관리하려다가, 구현하다 보니 각 서로소 집합 안에 존재하는 남녀 수 정보가 각각 필요해서 `(남자수, 여자수)` 튜플로 관리했다.