너와!나의!알고!리즘!/백준
[백준 #14500,Python] 테트로미노
moongchi98
2021. 5. 13. 23:59
[문제]
폴리오미노란 크기가 1×1인 정사각형을 여러 개 이어서 붙인 도형이며, 다음과 같은 조건을 만족해야 한다.
- 정사각형은 서로 겹치면 안 된다.
- 도형은 모두 연결되어 있어야 한다.
- 정사각형의 변끼리 연결되어 있어야 한다. 즉, 꼭짓점과 꼭짓점만 맞닿아 있으면 안 된다.
정사각형 4개를 이어 붙인 폴리오미노는 테트로미노라고 하며, 다음과 같은 5가지가 있다.
아름이는 크기가 N×M인 종이 위에 테트로미노 하나를 놓으려고 한다. 종이는 1×1 크기의 칸으로 나누어져 있으며, 각각의 칸에는 정수가 하나 쓰여 있다.
테트로미노 하나를 적절히 놓아서 테트로미노가 놓인 칸에 쓰여 있는 수들의 합을 최대로 하는 프로그램을 작성하시오.
테트로미노는 반드시 한 정사각형이 정확히 하나의 칸을 포함하도록 놓아야 하며, 회전이나 대칭을 시켜도 된다.
[풀이]
처음에는 저 모든 테트로미노를 여기에 채워넣어야 하는 문제인줄 알고,,문제를 골라주신 동건이형이 나를 과대평가 한거 아닐까,,? 라고 생각했다 ^^,, 근데 그냥 간단하게 저 모양으로 가능한 모든 숫자 4개의 합을 결정하면 된당.
처음에는 어제 푼 소문난 칠공주처럼 하면 딱이다! 하고 만들었다. (4가지 조합 다 만들고, 이웃 점검) 그런데 답은 맞게 나오는 거 같은데 시간초과가 난다^^,,그것두 1%도 올라가지 않음 참눼^^,,,, 그래서 아,.,,어쩌지 하다가 다른 분들의 풀이를 참고해서 모든 경우의 수를 만들면 된다는 것을 알았다.. 유레카!
🐰 모든 조합의 수 만들어서 한 풀이
from sys import stdin
N,M = map(int,stdin.readline().split())
arr = [list(map(int,stdin.readline().split())) for _ in range(N)]
all_kind= [
[(0, 0), (0, 1), (1, 0), (1, 1)], # ㅁ
[(0, 0), (0, 1), (0, 2), (0, 3)], # ㅡ
[(0, 0), (1, 0), (2, 0), (3, 0)], # ㅣ
[(0, 0), (0, 1), (0, 2), (1, 0)],
[(1, 0), (1, 1), (1, 2), (0, 2)],
[(0, 0), (1, 0), (1, 1), (1, 2)], # ㄴ
[(0, 0), (0, 1), (0, 2), (1, 2)], # ㄱ
[(0, 0), (1, 0), (2, 0), (2, 1)],
[(2, 0), (2, 1), (1, 1), (0, 1)],
[(0, 0), (0, 1), (1, 0), (2, 0)],
[(0, 0), (0, 1), (1, 1), (2, 1)],
[(0, 0), (0, 1), (0, 2), (1, 1)], # ㅜ
[(1, 0), (1, 1), (1, 2), (0, 1)], # ㅗ
[(0, 0), (1, 0), (2, 0), (1, 1)], # ㅏ
[(1, 0), (0, 1), (1, 1), (2, 1)], # ㅓ
[(1, 0), (2, 0), (0, 1), (1, 1)],
[(0, 0), (1, 0), (1, 1), (2, 1)],
[(1, 0), (0, 1), (1, 1), (0, 2)],
[(0, 0), (0, 1), (1, 1), (1, 2)]]
max_total = 0
for i in range(N):
for j in range(M):
for s in all_kind:
total = 0
for x in range(4):
nr = i + s[x][0]
nc = j + s[x][1]
if 0<=nr<N and 0<=nc<M:
total += arr[nr][nc]
if total > max_total:
max_total = total
print(max_total)
🐤 소문난 칠공주 처럼 모든 조합 만들고, 이웃 찾기 => 시간 초과 코드
#시간초과
from sys import stdin
def combi(idx,total,q,i):
global max_total,visit_check
if i>=N*M or N*M-i<4-idx:
return
if idx == 4:
if total > max_total:
check(q[0],q)
if sum(sum(visit_check,[])) == 4:
max_total = total
visit_check =[[0]*M for _ in range(N)]
return
tmp.append(i)
combi(idx+1,total+arr[i],q+[i],i+1)
tmp.pop()
combi(idx,total,q,i+1)
def check(s,q):
q = set(q)
r = s // M
c = s % M
visit_check[r][c] = 1
for i in range(4):
nr = r + dr[i]
nc = c + dc[i]
if 0<=nr<N and 0<=nc<M and visit_check[nr][nc] == 0:
next = (nr*M+nc)
if next in q:
check(next,q)
N,M = map(int,stdin.readline().split())
arr =[]
for _ in range(N):
arr += list(map(int,stdin.readline().split()))
visit = [0]*(N*M)
visit_check =[[0]*M for _ in range(N)]
dr = [-1,1,0,0]
dc = [0,0,-1,1]
tmp = []
max_total = 0
combi(0,0,[],0)
print(max_total)