https://www.acmicpc.net/problem/17140
17140번: 이차원 배열과 연산
첫째 줄에 r, c, k가 주어진다. (1 ≤ r, c, k ≤ 100) 둘째 줄부터 3개의 줄에 배열 A에 들어있는 수가 주어진다. 배열 A에 들어있는 수는 100보다 작거나 같은 자연수이다.
www.acmicpc.net
처음 이 문제를 봤을때 dic를 쓸까 생각했지만 사용하기 어려워 list와 set을 사용해 풀었다.
시간초과나 메모리초과가 나오는 것인지 떨리면서 제출했는데 생각보다 시간이 별로 안 걸려서 놀랐다.
여러 시행착오가 있었지만 AC받았다.
실수 1. dp배열에 크기를 작게 해줘서 index에러가 났다. K<=100번이니 dp배열의 크기를 101로 해줬더니 에러가 안 났다.
실수 2. C연산에서 변경하고 남은 밑에 열을 0으로 초기화 해주지 않아서 잘못된 답이 나왔다. 초기화 해주니 알맞은 답이 나왔다.
def R(s): #R연산을 해주는 함수
maxs=-1#행의 길이의 최댓값
for i in range(len(s)):
s2=[]#정렬된 리스트가 담길 리스트
c=0#행의 길이
for k in set(s[i]):#시간 복잡도를 줄이기 위해 set을 사용
if k!=0:
s2.append([s[i].count(k),k])#s[i]배열에 있는 k의 개수를 k와 함께 저장.
s2.sort()#정렬된 상태로 집어 넣으니 정렬해줌
s[i]=[]#인덱스 하나하나 바꿔주는 방법도 있으나 시간 복잡도상으로 append를 써도 돼 빈리스트로 만든 뒤 추가해줌
for o in s2:#s2에는 [[k개수,k],...,[k개수,k]]상태로 저장돼있음
s[i].append(o[1])#정렬은 [k,k개수]이런 형식으로 정렬되니 저런 작업을 해줌
s[i].append(o[0])
c+=2#행의 길이가 2만큼 늘어나니 +2
maxs = max(maxs,c)#최댓값 갱신
for i in range(len(s)):
s[i]+=[0]*(maxs-len(s[i]))#최댓값에 비해 부족한 길이를 더해줌
def C(s):#C연산을 해주는 함수
t = len(s)#열의 길이가 달라질 수 있으니 변수로 저장
dc = len(s[0])#행의 길이가 달라질 수 있으니 변수로 저장
re=[]#행과 달리 append를 못 쓰고 index하나하나에 접근해야 함으로 정렬된 값을 저장해주는 리스트
maxs=-1#열의 길이의 최댓값
for i in range(len(s[0])):
re.append([])
s2=[]
dp=[0]*(101)#숫자가 몇번 나오는지 count하기 위해 만든 배열
for j in range(t):#열 탐색
if s[j][i]!=0:
s2.append(s[j][i])#뭔 숫자가 있는지 더해줌 나중에 set을 사용해 dp에 접근할것이기 때문
dp[s[j][i]]+=1 #count해줌
sre = set(s2)
for k in sre:
re[i].append([dp[k],k])#R함수와 같은 원리로 정렬시켜 저장해줌
re[i].sort()
maxs = max(maxs,len(sre))#열의 최댓값
for _ in range(2*maxs-len(s)):#2*maxs인 이유 len(sre)가 1개가 늘어나면 열은 2개가 필요함
s.append([0]*dc)# [0]*행의 최대 길이인으로 채워진 열을 행을 추가해 열의 길이를 늘려줌
for i in range(dc):
for j,k in enumerate(re[i]):#enumerate를 사용해 index에 접근후 저장된 값으로 변경
s[j*2][i]=k[1]
s[j*2+1][i]=k[0]
for k in range(j*2+2,len(s)):#위에 변경했는데 이전 정보가 남아 있을 수 있으니 0으로 치환
s[k][i]=0
r,c,k=map(int,input().split())
s = [list(map(int,input().split())) for _ in range(3)]
t=0
try:#처음부터 정답인 경우는 바로 출력 r,c가 리스트 범위를 벗어날 수 있으니 예외처리
if s[r-1][c-1]==k:
print(t)
t=102
except:
pass
while t<=100:#최대 100번이니 t가 100보다 크거나 같을때까지만
t+=1
rl,cl = len(s),len(s[0])#R연산인지 C연산인지 확인해주기 위한것
if rl>=cl:
R(s)
else:
C(s)
try:연산후 정답인 경우는 바로 출력 r,c가 리스트 범위를 벗어날 수 있으니 예외처리
if s[r-1][c-1]==k:
print(t)
break
except:
pass
if t==101:#100번 연산했는데 답이 안 나왔음으로 -1 출력
print(-1)
'백준 파이썬 코딩' 카테고리의 다른 글
백준 1015 수열 정렬 파이썬 (0) | 2022.08.15 |
---|---|
백준 17140 이차원 배열과 연산 파이썬 *추가* (0) | 2022.08.15 |
백준 2417 정수 제곱근 파이썬 (0) | 2022.08.14 |
백준 10986 나머지 합 파이썬 (0) | 2022.08.13 |
백준 2573 빙산 파이썬 (DFS) (0) | 2022.08.13 |