만족은 하되 안주하지는 말자

기록해야 기억한다

프로그래밍/programmers&bj

[python] 백준 14500번: 테트로미노

D36choi 2020. 10. 3. 00:43
728x90

문제

www.acmicpc.net/problem/14500

 

14500번: 테트로미노

폴리오미노란 크기가 1×1인 정사각형을 여러 개 이어서 붙인 도형이며, 다음과 같은 조건을 만족해야 한다. 정사각형은 서로 겹치면 안 된다. 도형은 모두 연결되어 있어야 한다. 정사각형의 변�

www.acmicpc.net

테마

브루트포스

 

아이디어

 

테트로미노들은 기본모양에서 90도씩 회전, x/y축 반전(뒤집기) 등이 가능하다. 네모의 칸수는 총 4칸.

 

돌리고 뒤집고 돌리고 뒤집고 ...

 

[[0,0,0],

 [0,0,0],

 [0,0,0]]

 

3*3 이내의 좌표로 모든 테트로미노의 좌표가 표현 가능하다. 무식하지만 총 19개의 테트로미노 경우의 수

'tetrominos' 배열에 저장해 활용했다. 

 

N*M 배열에서 각 i행j열 좌표를 시작점으로 하는 모든 테트로미노의 경우의 수들을 cal_sum() 함수로 테트로미노 좌표의

값의 합을 구하고 이를 기존의 max_sum(최댓값) 과 max() 함수를 통해 최댓값을 갱신해나간다.

만약 좌표 범위내를 벗어나는 테트로미노의 경우에는

cal_sum() 함수에서 바로 '-1' 을 리턴해 최댓값이 갱신되지도 않고 반복문을 계속 돌리지도 않게 한다.

 

 

시간복잡도

시간복잡도는 O(N*M) 이다.

가능한 최대연산횟수를 계산해보면 N=4,M=200 일 때

4*200*19 = 15200 가 된다. 이는 생각보다 훠우워어얼씬 크지 않은 수다.

시간복잡도는 O(N*M) 이지만 실질적으로 상수인 테트로미노의 경우의 수 19를 무시할만큼 N 의 범위가 크지는 않다.

 

코드

 

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
from sys import stdin
tetrominos = [([00], [01], [02], [03]),  # ----
              ([00], [10], [20], [30]),
              ([00], [01], [11], [10]),  # ㅁ
              # ㄴ 모양
              ([00], [10], [11], [12]),
              ([00], [01], [10], [20]),
              ([00], [01], [02], [12]),
              ([01], [11], [21], [20]),
              ([00], [01], [11], [21]),
              ([10], [11], [12], [02]),
              ([00], [10], [20], [21]),
              ([00], [10], [01], [02]),
              # 번개모양
              ([00], [10], [11], [21]),
              ([10], [11], [01], [02]),
              ([20], [10], [11], [01]),
              ([00], [01], [11], [12]),
              # ㅜ 모양
              ([00], [01], [11], [02]),
              ([10], [01], [11], [21]),
              ([10], [11], [12], [01]),
              ([00], [10], [11], [20])]
 
def cal_sum(r, c, t ):  # t: 해당 tetromino 의 좌표 모음
    summ = 0
    global N, M
    for dx, dy in t:
        nx = r + dx
        ny = c + dy
        if 0 <= nx < N and 0 <= ny < M:
            summ += board[nx][ny]
        else:
            return -1
    return summ
 
 
N, M = map(int, stdin.readline().split())
board = []
for n in range(N):
    board.append(list(map(int, stdin.readline().split(' '))))
ans = 0
max_sum = 0
for r in range(N):
    for c in range(M):
        for tetromino in tetrominos:
            max_sum = max(max_sum, cal_sum(r, c, tetromino))
 
# edge-case : 19 (테트로미노 경우의 수) * 4 * 200 = 15200번 연산.
print(max_sum)
 
cs