코딩테스트 풀이/백준
[BAEKJOON] 20002번 사과나무 - 완전탐색, DP
개발하는 감자입니다
2024. 4. 19. 00:55
728x90
안녕하세요, 개발감자입니다.
오늘은 20002번 사과나무 문제풀이를 해보려고 합니다.
20002번: 사과나무
N × N 크기의 정사각형 모양 과수원이 있고, N × N 개의 사과나무가 1 × 1 크기의 간격으로 모든 칸에 심어져있다. 농부 형곤이가 가을을 맞아 사과를 수확하려는데, 땅주인 신영이가 "너는 과수원
www.acmicpc.net
1. 문제 풀이
문제를 분석해본 결과, 완전 탐색을 할 수 밖에 없는 문제라는 것을 깨달았습니다. 어쨌든 모든 경우의 수를 확인하여 형곤이가 최대 총이익을 얻을 수 있는 경우를 구해야 하기 때문입니다. 총이익을 구하는 과정에서 중복되는 연산이 많은 것을 확인하였습니다.
이 문제는 완전 탐색을 베이스로 하되, dp를 활용하여 메모리 초과를 방지하는 풀이 방법으로 접근해야 합니다.
2. 코드
# 입력 받기
n = int(input())
apple = [list(map(int, input().split())) for _ in range(n)] # 사과를 통해 얻은 이익, 노동비 = 총이익 정리
# 1 <= K <= n : 농부 형곤이가 가져갈 수 있는 정사각형의 모양
answer = 0
# DP - 총이익의 합을 메모제이션하기
# -> 완전 탐색, 모든 경우의 수를 다 확인해야 함. 겹치는 연산이 많음
# 메모제이션 실시
sum = [[0] *n for _ in range(n)]
for i in range(n):
for j in range(n):
if i == j == 0 :
sum[i][j] = apple[i][j]
elif j == 0:
sum [i][0] = sum [i-1][0] + apple[i][j]
elif i == 0:
sum [0][j] = sum [0][j-1] + apple[i][j]
else:
sum[i][j] = apple[i][j] + sum[i-1][j] + sum[i][j-1] - sum[i-1][j-1]
def check_bigger(n1, n2):
if n1 >= n2 :
return n1
if n2 > n1 :
return n2
def in_range(i,j):
return 0 <= i < n and 0<= j < n
answer = sum[0][0]
for k in range(1,n):
for i in range(n):
for j in range(n):
if i < k-1 or j < k-1:
continue
if k == 1:
temp = apple[i][j]
else:
temp = sum[i][j]
check1 = in_range(i-k,j)
check2 = in_range(i,j-k)
if check1:
temp -= sum[i - k][j]
if check2:
temp -= sum[i][j - k]
if check1 and check2:
temp += sum[i - k][j - k]
#print(temp)
answer = check_bigger(answer, temp)
# 최대 총익을 안겨주자
print(answer)
728x90
반응형