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 |