문제링크
https://programmers.co.kr/learn/courses/30/lessons/92344
무지성으로 풀면 무조건 시간초과난다
이 문제는 정확성과 효율성이 따로 구분되어있다. 무조건 모든 방식에서 생각해봐야한다는거다
시간초과 코드는 하단에 첨부한다
사전지식 : 누적합
보통 구간의 합계를 sum(리스트시작:리스트끝) 이걸로 구하는데 이게 리스트길이만큼의 시간복잡도가 사용된다.
그러면 합산 한번당 O(n)이 걸리는데 당연히 연산 횟수가 많아지면 많아질수록 비례해서 길어질것이다
그런데 누적합을 사용한 방식은 누적합계를 더한다음에 리스트끝원소-리스트시작원소 를 지정해서 계산하는데
리스트인덱싱1개는 O(1)이거든요. 그래서 누적합은 O(1)+O(1) 시간에 구간의 합계를 구할수 있어서 사용한다.
사전지식 : 2차원 누적합
일반적인 누적합은 1차원에서 사용되는데, 지금 문제는 2차원 누적합을 사용한다.
[r1,c1] ~ [r2,c2] 에 +a 만큼 해줘야한다면
[r1,c1], [r2+1][c2+1] : +a
[r2+1,c1], [r1][c2+1] : -a
점을 찍고 가로로 한번 훝고, 세로로 한번 훝으면 된다
자세한거는 나도 참고한 링크를 첨부한다.
https://driip.me/65d9b58c-bf02-44bf-8fba-54d394ed21e0
소스코드
#testcase1
# board = [[5,5,5,5,5],[5,5,5,5,5],[5,5,5,5,5],[5,5,5,5,5]]
# skill = [[1,0,0,3,4,4],[1,2,0,2,3,2],[2,1,0,3,1,2],[1,0,1,3,3,1]]
#testcase2
board = [[1,2,3],[4,5,6],[7,8,9]]
skill = [[1,1,1,2,2,4],[1,0,0,1,1,2],[2,2,0,2,0,100]]
M, N = len(board[0]), len(board)
tile = [[0 for _ in range(M+1)] for _ in range(N+1)]
#이차원 누적합을 사용할거라 점찍기 과정
#시작점, [r2+1][c2+1] 에는 더해주고
#[r1][c2+1], [r2+1][c1] 에는 빼줄건데 ( 누적합에서 값 상쇄하기위함)
for type, r1, c1, r2, c2, degree in skill :
if type == 1 :
tile[r1][c1] += (-degree)
tile[r2+1][c2+1] += (-degree)
tile[r1][c2+1] -= (-degree)
tile[r2+1][c1] -= (-degree)
else :
tile[r1][c1] += degree
tile[r2 + 1][c2 + 1] += degree
tile[r1][c2+1] -= degree
tile[r2+1][c1] -= degree
#가로 누적합
for j in range(0,N+1) :
for i in range(1,M+1) :
tile[j][i] += tile[j][i-1]
#세로 누적합
for i in range(0,M+1) :
for j in range(1,N+1) :
tile[j][i] += tile[j-1][i]
#누적합 결과와 초기값을 합산
answer = 0
for j in range(N) :
for i in range(M) :
if board[j][i] + tile[j][i] > 0 :
answer += 1
print(answer)
시간초과 코드
#시간초과 나는 코드
def solution(board, skill):
answer = 0
def skil(type, r1, c1, r2, c2, degree):
if type == 1:
damage = True
else:
damage = False
if damage == True:
for i in range(r1, r2 + 1, 1):
for j in range(c1, c2 + 1, 1):
# print(i, j)
board[i][j] = board[i][j] - degree
else: # damage==False
for i in range(r1, r2 + 1, 1):
for j in range(c1, c2 + 1, 1):
# print(i, j)
board[i][j] = board[i][j] + degree
for i in skill:
type, r1, c1, r2, c2, degree = i
skil(type, r1, c1, r2, c2, degree)
# print(board)
cnt = 0
for i in range(len(board)):
for j in range(len(board[0])):
if board[i][j] > 0:
cnt += 1
answer = cnt
return answer
'CodingTest' 카테고리의 다른 글
백준 2109 순회강연 파이썬 (0) | 2022.07.01 |
---|---|
백준 13913 숨바꼭질4 파이썬 (0) | 2022.06.16 |
프로그래머스 60057 문자열압축 파이썬 (0) | 2022.06.15 |
Softeer GBC 파이썬 (0) | 2022.06.05 |
Softeer [21년 재직자 대회 예선] 비밀메뉴 파이썬 (0) | 2022.06.05 |