Skip to content

10월 2주차 문제풀이 #97

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

Open
wants to merge 2 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
Binary file added ParkJunHa/.DS_Store
Binary file not shown.
26 changes: 26 additions & 0 deletions ParkJunHa/10월 2주차/가르침.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
from string import ascii_lowercase
from itertools import combinations

n, k = map(int, input().split())
k -= 5

remains = {'a', 'c', 'i', 'n', 't'}
alpha = {*ascii_lowercase} - remains
if k < 0:
print(0)
exit()

mx = 0

strset = [{*input()} for _ in range(n)]
for c in combinations(alpha, k):
tmp = 0
remains = remains | {*c}
for s in strset:
if remains.issuperset(s):
# print(remains, *c)
tmp += 1

remains = remains - {*c}
mx = max(mx, tmp)
print(mx)
22 changes: 22 additions & 0 deletions ParkJunHa/10월 2주차/빗물.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
width, height = map(int, input().split())
stack = map(int, input().split())
graph = [[0]* height for _ in range(width)]
res = 0

for i, s in enumerate(stack):
for j in range(s):
graph[j][i] = 1

for i in range(width):
for j in range(height):
if graph[i][j] == 0:
graph[i][j] = 9

for k in range(height):
if graph[i][k] == 9:
try:
w_s, w_e = graph[i][:k].index(1), graph[i][k+1:].index(1)
except ValueError:
graph[i][k] = -1

print(sum(graph, []).count(9))
29 changes: 29 additions & 0 deletions ParkJunHa/10월 2주차/회전_초밥.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import sys
input = sys.stdin.readline
from collections import defaultdict

N, d, k, c = map(int,input().split())
sushi = []
for _ in range(N):
sushi.append(int(input()))
sushi.extend(sushi)

left = 0
right = 0
max_cnt = 0
eat = defaultdict(int)

eat[c] += 1

for right in range(len(sushi)):
eat[sushi[right]] += 1

if right >= k-1:
max_cnt = max(max_cnt,len(eat))
print(max_cnt)
eat[sushi[left]] -= 1
if eat[sushi[left]] == 0:
del eat[sushi[left]]
left += 1

print(max_cnt)
56 changes: 56 additions & 0 deletions ParkJunHa/note/1062-가르침.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
---
platform: BOJ
link: https://www.acmicpc.net/problem/1062
tags:
- bitmask
- bruteforcing
difficulty: g4
정답 참조:
is_study: true
week-date:
- 10월
- 2주차
---
`=this.file.tags`

# \[`=this.file.frontmatter.platform`\]`=this.file.name`


### 풀이
#### 아이디어
일단 남극어는 anta - tica 구조이므로 집합 {a,c,i,n,t}를 제외한 나머지 조합탐색을 통해서 한다.
무작정 찾게 되면 시간 낭비가 날 것 같아 set 자료구조를 사용했다.

그래서 단어를 입력받고, 각 단어마다 백트래킹과 유사한 방식으로 탐색한 조합을 remains에 넣었다 뺐다 하면서 최댓값을 찾는 방식으로 진행하였다.
#### 코드
```python
from string import ascii_lowercase
from itertools import combinations

n, k = map(int, input().split())
k -= 5

remains = {'a', 'c', 'i', 'n', 't'}
alpha = {*ascii_lowercase} - remains
if k < 0:
print(0)
exit()

mx = 0

strset = [{*input()} for _ in range(n)]
for c in combinations(alpha, k):
tmp = 0
remains = remains | {*c}
for s in strset:
if remains.issuperset(s):
# print(remains, *c)
tmp += 1

remains = remains - {*c}
mx = max(mx, tmp)
print(mx)
```
---
### 회고
이게 되네
52 changes: 52 additions & 0 deletions ParkJunHa/note/14179-빗물.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
---
platform: BOJ
link: https://www.acmicpc.net/problem/14179
tags:
- implements
- simulation
difficulty: g5
정답 참조:
is_study: true
week-date:
- 10월
- 2주차
---

# \[`=this.file.frontmatter.platform`\]`=this.file.name`


### 풀이
#### 아이디어
우선 width, height대로 실제 그래프를 만들고, 빗물이 떨어진다면 아래의 조건을 만족한 경우 빗물이 고일수 있으므로 그대로 구현하였다.
1. 일단 비는 내린다
2. 양쪽이 막혔는지 확인한다.
3. 만약 막히지 않는 곳이라면 그 위로부터는 쌓지 못한다.
#### 코드
```python
width, height = map(int, input().split())
stack = map(int, input().split())
graph = [[0]* height for _ in range(width)]
res = 0

for i, s in enumerate(stack):
for j in range(s):
graph[j][i] = 1

for i in range(width):
for j in range(height):
if graph[i][j] == 0:
graph[i][j] = 9

for k in range(height):
if graph[i][k] == 9:
try:
w_s, w_e = graph[i][:k].index(1), graph[i][k+1:].index(1)
except ValueError:
graph[i][k] = -1

print(sum(graph, []).count(9))

```
---
### 회고
간만에 힐링문제였다. 요즘 PS문제를 어려운것밖에 안해서 흥미가 떨어질뻔 했는데 뇌 빼고 해도 풀리는 문제 하니 다시 재밌어졌다. 다만 위 문제 조건에서 아무리 해봐야 최종 계산이 1억을 넘지 않는다는것을 확인했고 그래서 뇌빼고 풀 수 있었던거라 숫자가 커지면 시간복잡도는 지수시간 비스무리하게 커질것으로 보인다. 또한 PS에서 count라던가 index라던가 뭐 del이라던가 이런 인스턴스들 쓰는거 별로 안좋아하는데 그런면에서는 마음에 들지 않은 코드이다.
95 changes: 95 additions & 0 deletions ParkJunHa/note/15961-회전초밥.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
---
platform: BOJ
link: https://www.acmicpc.net/problem/15961
tags:
- two_pointer
- sliding_window
difficulty: g4
정답 참조: true
is_study: true
week-date:
- 10월
- 2주차
---

# \[`=this.file.frontmatter.platform`\]`=this.file.name`


### 풀이
#### 아이디어
우선 코드부터 첨부한다.
```python
import sys
input = sys.stdin.readline

plate, kinda, series, cupon = map(int, input().split())
lane = list(int(input()) for _ in range(plate))*2
# res = [[0, 0] for _ in range(plate+1)] # 가짓수, 종류수
res = [0]*(plate+1)

sp, ep = 0, series

while sp <= plate:
window, kind = lane[sp:ep], len(set(lane[sp:ep]))
# print(window, kind)
# res[sp][0], res[sp][1] = kind, kind
res[sp] = kind
if cupon not in window:
# res[sp][0] += 1
res[sp] += 1

sp, ep = sp+1, ep+1

# print(sorted(res, key = lambda x:(-x[0], -x[1])))
print(max(res))
```
아이디어는 연속으로 먹은 초밥을 슬라이싱하고, 최대한 많은 종류의 초밥을 먹어야하므로, `set`을 이용해서 중복을 제거한 개수를 저장해주었다.

지금 와서 보니까 문제를 잘못읽은 부분이 있는데, 만약 쿠폰으로 받은 초밥번호가 내가 연속으로 먹는 초밥 시리즈에 없다면 1개를 더해준다. 이부분은 문제에서 "초밥이 없다면 만들어준다"라는 조건을 빼고 봐서 그렇다.

이 코드는 우선 시간초과가 발생한다. 그도그럴것이 6백만 크기의 리스트 인덱싱을 반복하니까 $N \times (N-1)$정도의 연산이 반복된다. 또한 인덱싱은 인덱싱 크기만큼의 연산이 추가로 필요하므로 series를 s라고 했을때 저기에 s를 또 곱해줘야한다..


#### 코드
```python
import sys
input = sys.stdin.readline
from collections import defaultdict

N, d, k, c = map(int,input().split())
sushi = []
for _ in range(N):
sushi.append(int(input()))
sushi.extend(sushi)

left = 0
right = 0
max_cnt = 0
eat = defaultdict(int)

eat[c] += 1

for right in range(len(sushi)):
eat[sushi[right]] += 1

if right >= k-1:
max_cnt = max(max_cnt,len(eat))
eat[sushi[left]] -= 1
if eat[sushi[left]] == 0:
del eat[sushi[left]]
left += 1

print(max_cnt)
```
1. 나는 리스트 크기를 2배로 늘릴때 곱 연산을 이용했지만 코드에서는 `.extend()`를 사용했다.
2. `eat`이라는 변수에 값이 없는 딕셔너리 (default dict)을 생성하였고, 실제로 시뮬레이션 하듯이 먹고 빼고를 반복한다.
3. 쿠폰으로 주는 초밥은 무조건 먹으므로 c에 1을 더해준다.
4. 슬라이딩 윈도우를 적용해주는데, k 만큼은 무조건 먹고, 만약 오른쪽 포인터가 그 이상이 갔을때, 왼쪽 포인터를 옮겨주고, 해당 위치에 있는 초밥의 개수를 줄여준다
5. 만약 초밥을 줄였을때 개수가 0이라면 해당 키를 삭제시켜 개수를 업데이트해준다.


> 즉 딕셔너리가 저장하는 값은 각각의 번호의 초밥을 몇개 먹었는가? 를 저장하며, 그 종류의 개수를 세어 가장 큰 값을 정답으로 한다.

---
### 회고
슬라이딩 윈도우라는 주제를 제대로 풀어본적이 없어 아이디어를 떠올리기 쉽지 않았던 문제.