[BOJ] 7573 고기잡이 (Python3)

3 분 소요

문제

한국인의 식단에서 생선은 매우 중요한 단백질 공급원이다. 반면, 지구 온난화로 인한 바닷물의 온도 상승, 그리고 지금까지 마구잡이로 물고기를 잡은 결과로 점점 우리나라의 바다에서 물고기의 수가 줄어들고 있다. 정부에서는 이 문제를 심각하게 생각하여, 물고기를 잡을 수 있는 곳과 여기서 고기잡이 배가 사용할 수 있는 그물의 폭에 제한을 두었다. 물고기는 바다 표면 근처에 살기 때문에, 그물의 높이는 중요하지 않다. 따라서 그물은 길이가 l인 직선으로 생각할 수 있고, 물고기를 잡을 때, 그물은 한 변의 길이가 1 이상 정수인 직사각형 모양으로 치게 된다. 예를 들어, l = 10이라면, 칠 수 있는 그물의 모양은 1×4, 2×3, 3×2, 4×1과 같이 4가지 형태의 직사각형이 된다.

고기를 잡을 수 있는 곳은 N×N 크기의 모눈종이 모양으로 되어 있다. 각 모눈에는 좌표가 주어지며, 가장 왼쪽 위 모눈이 (1,1)이고, 가장 오른쪽 아래 모눈이 (N,N)이다. 총 M 마리의 물고기가 서로 다른 모눈 위에 한 마리씩 살고 있으며, 물고기는 움직이지 않는다. 고기잡이 배는 한 모눈 위에 위치를 잡고 자신의 오른쪽과 아래쪽으로 그물을 친다. 일단 그물을 치면, 그물 안, 그리고 그물에 걸친 물고기들을 잡을 수 있다. 예를 들면, 다음 그림은 N = 7, l = 10 이고 M = 6 마리의 물고기가 (2,2), (2,4), (3,3), (5,6), (6,2), (7,4)에 살고 있을 때, (2,2)에 놓인 고기잡이 배가 2×3 모양으로 그물을 친 예를 보이고 있다. 이때 고기잡이 배는 총 3마리의 물고기를 잡을 수 있다. 고기를 잡을 수 있는 영역 밖으로 그물을 치는 경우는 없다.

고기를 잡을 수 있는 영역, 물고기의 위치, 그물의 폭이 주어졌을 때 한 번의 그물치기로 잡을 수 있는 가장 많은 물고기의 마릿수를 구하는 프로그램을 작성하시오.

입력

첫 번째 줄에는 모눈종이의 크기, 그물의 길이, 물고기의 수를 나타내는 세 개의 정수 N, l, M이 하나의 공백을 두고 주어진다. 단, 2 ≤ N ≤ 10,000, 4 ≤ l ≤ 100, 1 ≤ M ≤100 이다. l은 l ≤ 4N - 4을 만족하는 짝수이다. 두 번째 줄부터 이후 M 개의 줄에는 각 물고기의 좌표가 하나의 공백을 두고 주어진다. 물고기의 좌표 순서는 무작위로 주어진다.

출력

첫 줄에 주어진 입력에서 잡을 수 있는 가장 많은 물고기의 마릿수를 하나의 정수로 출력한다.

정답 코드

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
import sys 
input = sys.stdin.readline

n, l, m = map(int, input().split())
fish = []

for i in range(m):
    x, y = map(int, input().split())
    fish.append((x, y))



def getNet(n):
    netSize = l // 2
    
    nets = []
    
    for i in range(1, netSize):
        netX = netSize - i
        netY = i
        
        nets.append((netX, netY))
    return nets
        
nets = getNet(n)

answer = 0

for net in nets:
    for fx, fy in fish:
        for mx in range(net[0] + 1):
            nx = fx - mx
            ny = fy
            
            if nx < 0 or nx >= n or ny < 0 or ny >=n:
                continue
            
            count = 0
            
            for rx, ry in fish:
                if nx <= rx <= nx + net[0] and ny <= ry <= ny + net[1]:
                    count += 1
                    
            
            answer = max(answer, count)
            
        for my in range(net[1] + 1):
            nx = fx
            ny = fy - my
            
            if nx < 0 or nx >= n or ny < 0 or ny >=n:
                continue
            
            count = 0
            
            for rx, ry in fish:
                if nx <= rx <= nx + net[0] and ny <= ry <= ny + net[1]:
                    count += 1
                    
            
            answer = max(answer, count)
            
print(answer)

문제 풀이

처음에는 그래프로 실제 그물을 이차원 배열로 표현했는데, 이렇게 하면 메모리초과가 발생한다.

다시 생각해보면 이 문제는 실제로 공간을 표현할 필요 없이, 그물의 공간범위에 포함 되는 물고기가 몇개인지만 확인해주면 답을 찾을 수 있다.

중요한건 각 물고기 별로 그물을 펼치되, 물고기가 꼭짓점에 있는 경우 외에도 가장자리에 걸치는 부분까지 탐색해주어야 모든 테스트 케이스를 통과할 수 있다.

카테고리:

업데이트:

댓글남기기