def Innerbound(x,y):
if 0<=x<N and 0<=y<M:
return True
else:
return False
def dfs(idx,bit,total):
global result
if bit == 2**(N*M)-1:
result = max(result,total)
return
else:
if 2**idx&bit:
dfs(idx+1,bit,total)
else:
x,y = idx//M, idx%M
nx,ny = x,y
temp_bit = bit
temp_num = 0
while Innerbound(nx,ny):
if visited[nx][ny]:
next_idx = nx*M + ny
visited[nx][ny] = False
temp_bit = temp_bit|(2**next_idx)
temp_num = temp_num*10 + arr[nx][ny]
nx = nx + 1
ny = ny
else:
break
for rx in range(nx-1,x-1,-1):
dfs(idx+1,temp_bit,total + temp_num)
temp_num = temp_num//10
next_idx = rx*M + y
temp_bit = temp_bit^(2**next_idx)
visited[rx][y] = True
nx,ny = x,y
temp_bit = bit
temp_num = 0
while Innerbound(nx,ny):
if visited[nx][ny]:
next_idx = nx*M + ny
visited[nx][ny] = False
temp_bit = temp_bit|(2**next_idx)
temp_num = temp_num*10 + arr[nx][ny]
nx = nx
ny = ny + 1
else:
break
for ry in range(ny-1,y-1,-1):
dfs(idx+1,temp_bit,total + temp_num)
temp_num = temp_num//10
next_idx = x*M + ry
temp_bit = temp_bit^(2**next_idx)
visited[x][ry] = True
N,M = map(int,input().split())
arr = [list(map(int,list(input()))) for _ in range(N)]
visited = [[True for _ in range(M)] for _ in range(N)]
result = 0
dfs(0,0,0)
print(result)
처음에 모든 경우들을 각각 하나씩 그려보면서 dfs를 해주었다.
가로 혹은 세로로 최대한 세울 수 있는 직사각형을 그려주고 그때부터 dfs를 하고 하나씩 내려주면서 dfs를 해주었다.
이 방식은 오래걸리는 방식이였고, 다른 사람들의 풀이를 보고 다시 푼 방식은 다음과 같다.
N,M = map(int,input().split())
arr = [list(map(int,list(input()))) for _ in range(N)]
result = 0
# 0은 가로인걸로 1은 세로인걸로 판별
for bit_shape in range(2**(N*M)):
total_sum = 0
for x in range(N):
sub_sum = 0 # 작은 단위의 SUM
for y in range(M):
idx = x*M + y
if not bit_shape & (1<<idx):
sub_sum = sub_sum*10 + arr[x][y]
else:
total_sum += sub_sum
sub_sum = 0
total_sum += sub_sum
for y in range(M):
sub_sum = 0
for x in range(N):
idx = x*M + y
if bit_shape & (1<<idx):
sub_sum = sub_sum*10 + arr[x][y]
else:
total_sum += sub_sum
sub_sum = 0
total_sum += sub_sum
result = max(result,total_sum)
print(result)
이 방식은 모든 경우를 먼저 구하는 거다. 이 문제는 최대 16개의 칸을 가지는 것이다.
이것을 비트로 표현해서 0이면 가로로 그려진 직사각형 1이면 세로인 직사각형으로 구분을 해주는것이다.
그러면 우리는 2**(N*M)의 경우의 수를 가질수 있다. 최대 65536가지이므로, 빠르게 구할 수 있다.
비트로 현재 종이조각의 상태를 구분하고, 그 상태에 맞게 숫자를 세서 최대값을 구하면 된다.
'알고리즘 > 백준' 카테고리의 다른 글
[BOJ/백준] 14938 서강그라운드 (0) | 2021.09.02 |
---|---|
[BOJ/백준] 14621 나만 안되는 연애 (0) | 2021.09.02 |
[BOJ/백준] 13418 학교 탐방하기 (0) | 2021.09.02 |
[BOJ/백준] 11780 플로이드 2 (0) | 2021.09.02 |
[BOJ/백준] 7511 소셜 네트워킹 어플리케이션 (0) | 2021.09.02 |