Skip to content

Commit c6c9787

Browse files
authored
Merge pull request #50 from bsa0322/jy/implement/py
[구현 & 코너케이스] 05월 16일 (필수+선택.py)
2 parents 65e36c7 + 05b5a40 commit c6c9787

File tree

7 files changed

+495
-0
lines changed

7 files changed

+495
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
import sys
2+
input = sys.stdin.readline
3+
MAX = 1000
4+
5+
"""
6+
[테트로미노]
7+
8+
1. 보라색 블럭을 제외하고는 모두 한붓 그리기로 그릴 수 있음
9+
-> 일반적인 백트래킹으로 모양을 만들 수 있음
10+
2. 보라색 블럭은 3개의 블럭이 결정된 이후에, 가운데에서 탐색을 해야 만들 수 있음
11+
-> 3번째 블럭을 결정하면서 현재 좌표를 갱신하지 않고, 직전 좌표에서 다시 한번 백트래킹을 진행하여 얻을 수 있음
12+
3. 각 블럭에 대해 깊이가 4인 백트래킹 함수를 수행하며 최댓값 갱신
13+
14+
방문처리 -> board를 활용해서 0을 저장하는 것으로
15+
가지치기 -> 현재 탐색이 남은 칸을 모두 MAX라 해도 ans이 더 큰 경우
16+
"""
17+
18+
# 한붓 그리기가 가능한 블럭들 백트래킹 탐색
19+
def backtracking(row, col, cnt, total):
20+
global ans # 전역변수 값에 업데이트가 있으므로
21+
22+
# 기저조건 : 4개의 블럭을 탐색함
23+
if cnt == 4:
24+
ans = max(ans, total)
25+
return
26+
27+
if ans >= MAX * (4 - cnt) + total:
28+
return
29+
30+
dr = [-1, 1, 0, 0]
31+
dc = [0, 0, -1, 1]
32+
33+
for i in range(4):
34+
nr = row + dr[i]
35+
nc = col + dc[i]
36+
37+
# 범위를 벗어나거나, 이미 방문 했다면
38+
if not (0 <= nr < n and 0 <= nc <m) or not board[nr][nc]:
39+
continue
40+
41+
if cnt == 2:
42+
save = board[nr][nc]
43+
board[nr][nc] = 0
44+
backtracking(row, col, cnt + 1, total + save)
45+
board[nr][nc] = save
46+
47+
save = board[nr][nc]
48+
board[nr][nc] = 0
49+
backtracking(nr, nc, cnt + 1, total + save)
50+
board[nr][nc] = save
51+
52+
53+
# 입력
54+
n, m = map(int, input().split())
55+
board = [list(map(int, input().split())) for _ in range(n)]
56+
57+
ans = 0
58+
59+
# 연산
60+
for i in range(n):
61+
for j in range(m):
62+
save = board[i][j]
63+
board[i][j] = 0
64+
backtracking(i, j, 1, save) # 모양 처리
65+
board[i][j] = save
66+
67+
# 출력
68+
print(ans)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
import sys
2+
input = sys.stdin.readline
3+
4+
"""
5+
[로봇 청소기]
6+
7+
board 정보 -> 0: 빈 칸, 1: 벽, 2: 청소한 공간
8+
step: 회전 카운트. 4가 되면 한 바퀴 돌아 다시 제자리로 돌아왔음을 의미
9+
10+
항상 첫 행, 마지막 행, 첫 열, 마지막 열은 벽이라고 문제에서 주어졌으므로 범위 검사를 할 필요가 없음
11+
"""
12+
13+
def cnt_clean_robot(r, c, d, board):
14+
# 상, 우, 하, 좌
15+
dr = [-1, 0, 1, 0]
16+
dc = [0, 1, 0, -1]
17+
18+
step = ans = 0
19+
20+
while True:
21+
if board[r][c] == 0:
22+
board[r][c] = 2
23+
ans += 1
24+
25+
if step == 4:
26+
if board[r - dr[d]][c - dc[d]] == 1:
27+
return ans
28+
29+
r -= dr[d]
30+
c -= dc[d]
31+
step = 0
32+
else:
33+
d = (d + 3) % 4
34+
if board[r + dr[d]][c + dc[d]]:
35+
step += 1
36+
continue
37+
38+
r += dr[d]
39+
c += dc[d]
40+
step = 0
41+
42+
# 입력
43+
n, m = map(int, input().split())
44+
r, c, d = map(int, input().split())
45+
46+
board = [list(map(int, input().split())) for _ in range(n)]
47+
48+
# 연산 + 출력
49+
print(cnt_clean_robot(r, c, d, board))
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,118 @@
1+
import sys
2+
from collections import deque
3+
input = sys.stdin.readline
4+
5+
"""
6+
[문제 설명] - 단순 구현 문제
7+
봄: 하나의 칸마다 나이가 어린 나무부터 자신의 나이만큼 양분을 먹고, 나이가 1 증가함
8+
각 칸에 양분이 부족해 자신의 나이만큼 양분을 못 먹는 나무는 즉시 죽음
9+
여름: 봄에 죽은 나무가 양분으로 변함. 죽은 나무마다 나이를 2로 나눈 값이 양분으로 추가 (소수점 버림)
10+
가을: 나이가 5의 배수인 나무가 번식. 인접한 8개 칸에 나이가 1인 나무가 생김
11+
겨울: 로봇(S2D2)이 땅을 돌아다니면서 A[r][c]만큼 각 칸에 양분 추가
12+
13+
K년이 지난 후 상도의 땅에 살아있는 나무의 개수
14+
15+
[문제 풀이]
16+
a: 로봇(S2D2)가 겨울에 주는 양분의 양
17+
land: 땅의 현재 양분 상태
18+
tree[i][j]: 해당 영역에 존재하는 나이와 개수를 튜플로 묶어서 덱에 저장
19+
- 새로운 나무가 번식하기 때문에, 나이에 대한 오름차순을 유지하기 위해서는 앞에서의 삽입이 필요
20+
21+
"""
22+
23+
# 봄을 거쳐 나이를 먹은 나무들에 의해 새롭게 태어나게 되는 나무의 수를 계산
24+
def breeding(breeding_src):
25+
dr = [-1, -1, -1, 0, 0, 1, 1, 1]
26+
dc = [-1, 0, 1, -1, 1, -1, 0, 1]
27+
28+
breeding_cnt = [[0]*n for _ in range(n)]
29+
30+
for r in range(n):
31+
for c in range(n):
32+
if breeding_src[r][c] == 0:
33+
continue
34+
for i in range(8):
35+
nr = r+dr[i]
36+
nc = c+dc[i]
37+
if 0 <= nr < n and 0 <= nc < n:
38+
breeding_cnt[nr][nc] += breeding_src[r][c]
39+
40+
return breeding_cnt
41+
42+
# 봄과 여름을 묶어서 진행
43+
def spring_summer():
44+
breeding_src = [[0]*n for _ in range(n)] # 나이가 5의 배수가 되어 가을에 번식을 하는 나무의 수를 각 영역에 저장
45+
46+
for i in range(n):
47+
for j in range(n):
48+
next_year = deque()
49+
dead = 0
50+
51+
while tree[i][j]:
52+
age, cnt = tree[i][j].popleft()
53+
# 해당 나이의 모든 나무에게 양분을 줄 수 없는 경우
54+
if land[i][j] < age * cnt:
55+
dead = cnt - land[i][j] // age
56+
cnt = land[i][j] // age # 살 수 있는 최대 수
57+
58+
if cnt > 0:
59+
land[i][j] -= age * cnt
60+
next_year.append((age+1, cnt))
61+
62+
if (age + 1) % 5 == 0:
63+
breeding_src[i][j] += cnt
64+
65+
# 죽은 나무가 생기면 그 이후의 나무는 모두 죽게 된다.
66+
if dead > 0:
67+
land[i][j] += (age // 2) * dead # 여름에 양분이 됨
68+
break
69+
70+
# 여름 -> 죽은 나무들이 양분이 됨
71+
while tree[i][j]:
72+
age, dead = tree[i][j].popleft()
73+
land[i][j] += (age // 2) * dead
74+
75+
tree[i][j] = next_year
76+
77+
return breeding_src
78+
79+
def autumn_winter(breeding_src):
80+
# 봄에 나이를 먹은 나무들의 번식 결과
81+
breeding_cnt = breeding(breeding_src)
82+
83+
for i in range(n):
84+
for j in range(n):
85+
# 가을 - 번식
86+
if breeding_cnt[i][j]:
87+
tree[i][j].appendleft((1, breeding_cnt[i][j]))
88+
# 겨울 - 로봇에 의해 양분 추가
89+
land[i][j] += winter_list[i][j]
90+
return
91+
92+
93+
# 입력
94+
n, m, k = map(int, input().split())
95+
winter_list = [list(map(int, input().split())) for _ in range(n)]
96+
97+
land = [[5]*n for _ in range(n)]
98+
tree = [[deque() for _ in range(n)] for _ in range(n)] # -> 만약 여기서 [deque()] * n으로 하면 어떻게 될까요?
99+
100+
for _ in range(m):
101+
x, y, z = map(int, input().split())
102+
tree[x-1][y-1].append((z, 1))
103+
104+
105+
# k년 동안 시뮬레이션
106+
for _ in range(k):
107+
breeding_src = spring_summer()
108+
autumn_winter(breeding_src)
109+
110+
ans = 0
111+
112+
# 남아 있는 나무 수 카운트
113+
for line in tree:
114+
for area in line:
115+
for _, cnt in area:
116+
ans += cnt
117+
118+
print(ans)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
import sys
2+
from collections import deque
3+
input = sys.stdin.readline
4+
5+
INF = 401
6+
7+
"""
8+
[아기 상어]
9+
10+
1. 상어로부터 가장 가까운 거리에 있는 모든 물고기 탐색 (BFS)
11+
2. 우선순위 조건에 맞추어 먹으러 갈 물고기 확정
12+
탐색하는 방향에 우선순위를 두는 걸로 해결되지 않음! (예제 입력 4) 정렬 필요
13+
3. 상어가 이동할 수 있는 곳이 없을 때까지 BFS 탐색 반복
14+
15+
입력 범위가 작기 때문에 매번 BFS 탐색을 반복해도 시간 초과 X
16+
가능한 물고기의 최대 마리 수 : 399마리
17+
최대 BFS 탐색 횟수 : 399회, 1회 탐색마다 while 문은 최대 400회 미만으로 순회
18+
총 연산 횟수 약 160000번으로 충분히 가능
19+
20+
해설 : https://myunji.tistory.com/378
21+
*글 자체는 별로 도움이 안되고...그냥 리팩토링하면 코드가 이렇게 되는구나 정도만 봐주세요
22+
"""
23+
24+
def next_pos(n, shark_size, shark, board):
25+
dr = [-1, 1, 0, 0]
26+
dc = [0, 0, -1, 1]
27+
28+
min_dist = INF
29+
que = deque() # 상어가 갈 수 있는 곳
30+
dist = [[0]*n for _ in range(n)] # 상어로부터의 거리 - 초기값은 0으로
31+
pos_list = [] # 상어가 먹을 수 있는 물고기들의 위치
32+
33+
dist[shark[0]][shark[1]] = 1
34+
que.append(shark)
35+
36+
while que:
37+
row, col = que.popleft()
38+
39+
# 최단거리 이상은 탐색할 필요 없음
40+
if dist[row][col] >= min_dist:
41+
continue
42+
43+
for i in range(4):
44+
nr = row + dr[i]
45+
nc = col + dc[i]
46+
if not (0 <= nr < n and 0 <= nc < n) or dist[nr][nc] or board[nr][nc] > shark_size:
47+
continue
48+
49+
dist[nr][nc] = dist[row][col] + 1
50+
51+
# 먹을 수 있는 물고기 발견
52+
if board[nr][nc] and board[nr][nc] < shark_size:
53+
pos_list.append((nr, nc))
54+
min_dist = dist[nr][nc]
55+
continue
56+
57+
que.append((nr, nc))
58+
59+
# 상어가 갈 수 있는 곳이 없음
60+
if not pos_list:
61+
return min_dist, (-1, -1)
62+
63+
pos_list.sort()
64+
65+
return min_dist - 1, pos_list[0]
66+
67+
def simulation(n, shark, board):
68+
ans = cnt = 0
69+
size = 2
70+
71+
while True:
72+
dist, pos = next_pos(n, size, shark, board)
73+
# 더 이상 먹을 수 있는 물고기가 공간에 없음
74+
if dist == INF:
75+
break
76+
77+
ans += dist
78+
cnt += 1
79+
80+
# 상어 크기 증가
81+
if cnt == size:
82+
cnt = 0
83+
size += 1
84+
85+
# 상어 이동
86+
board[shark[0]][shark[1]] = 0
87+
shark = pos
88+
89+
return ans
90+
91+
# 입력
92+
n = int(input())
93+
board = [list(map(int, input().split())) for _ in range(n)]
94+
95+
for i in range(n):
96+
for j in range(n):
97+
if board[i][j] == 9:
98+
shark_pos = (i, j)
99+
break
100+
101+
print(simulation(n, shark_pos, board))
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
import sys
2+
from collections import Counter
3+
input = sys.stdin.readline
4+
5+
SIZE = 26
6+
7+
"""
8+
[비슷한 단어]
9+
10+
단어가 같은 구성일 조건
11+
1. 두 개의 단어가 같은 종류의 문자로 이루어짐
12+
2. 같은 문자는 같은 개수만큼 있음
13+
14+
비슷한 단어의 조건
15+
1. 한 단어에서 한 문자를 더하거나, 빼면 같은 구성이 됨
16+
-> 두 단어에서 다른 문자의 개수가 총 1개
17+
2. 한 단어에서 한 문자를 바꾸면 같은 구성이 됨
18+
-> 두 단어에서 다른 문자의 개수가 총 2개
19+
-> !주의! 이때, 두 단어의 길이가 같아야 함 cf) doll | do
20+
21+
<Counter>
22+
- iterable한 객체를 받아서 횟수를 기록하여 Counter 객체로 반환.
23+
- 이때 Counter 객체는 유사 dictionary라고 생각할 수 있다.
24+
- 주의할 점은, 일반 dictionary와는 다르게 default 값이 0으로 설정되어 있어, 삽입하지 않은 키 값에 대한 조회가 가능하다.
25+
"""
26+
27+
# 입력
28+
n = int(input())
29+
30+
source = input().rstrip()
31+
source_cnt = Counter(source)
32+
ans = 0
33+
34+
alphabets = [chr(i + ord('A')) for i in range(SIZE)] # 알파벳 리스트
35+
36+
for _ in range(n-1):
37+
target = input().rstrip()
38+
diff = 0
39+
target_cnt = Counter(target)
40+
41+
for key in alphabets:
42+
diff += abs(target_cnt[key] - source_cnt[key]) # Counter 객체이므로 키가 존재하는지 확인 불필요
43+
44+
if diff <= 1 or (diff == 2 and len(target) == len(source)):
45+
ans += 1
46+
47+
print(ans)

0 commit comments

Comments
 (0)