반응형
문제
https://www.acmicpc.net/problem/1451
세준이는 N*M크기로 직사각형에 수를 N*M개 써놓았다.
세준이는 이 직사각형을 겹치지 않는 3개의 작은 직사각형으로 나누려고 한다. 각각의 칸은 단 하나의 작은 직사각형에 포함되어야 하고, 각각의 작은 직사각형은 적어도 하나의 숫자를 포함해야 한다.
어떤 작은 직사각형의 합은 그 속에 있는 수의 합이다. 입력으로 주어진 직사각형을 3개의 작은 직사각형으로 나누었을 때, 각각의 작은 직사각형의 합의 곱을 최대로 하는 프로그램을 작성하시오.
입력
첫째 줄에 직사각형의 세로 크기 N과 가로 크기 M이 주어진다. 둘째 줄부터 직사각형에 들어가는 수가 가장 윗 줄부터 한 줄에 하나씩 M개의 수가 주어진다. N과 M은 50보다 작거나 같은 자연수이고, 직사각형엔 적어도 3개의 수가 있다. 또, 직사각형에 들어가는 수는 한 자리의 숫자이다.
출력
세 개의 작은 직사각형의 합의 곱의 최댓값을 출력한다.
코드
n, m = map(int, input().split())
# 입력받은 전체 직사각형을 저장하기 위한 리스트(편리한 인덱싱을 위해 행 삽입)
rectangle_input = [[0 for _ in range(m + 1)]]
for _ in range(n):
# 라인별로 읽고 rectangle_input에 저장(편리한 인덱싱을 위해 [0] 삽입)
line_input = [0] + list(map(int, list(input())))
rectangle_input.append(line_input)
# 답은 최댓값을 출력해야 하므로, 0으로 시작
ans = 0
# 합을 저장할 리스트
s = [[0 for _ in range(m+1)] for _ in range(n+1)]
# 리스트 s는 입력받은 직사각형의 1,1부터 영역 내 모든 수의 합을 저장
for row in range(1, n + 1):
for col in range(1, m + 1):
s[row][col] = s[row - 1][col] + s[row][col - 1] - s[row - 1][col - 1] + rectangle_input[row][col]
def sum_cal(x1, y1, x2, y2):
return s[x2][y2] - s[x2][y1-1] - s[x1-1][y2] + s[x1-1][y1-1]
# 첫 번째 경우: 전체 직사각형을 세로로만 분할한 경우
for i in range(1, m-1):
for j in range(i+1, m):
r1 = sum_cal(1, 1, n, i)
r2 = sum_cal(1, i+1, n, j)
r3 = sum_cal(1, j+1, n, m)
if ans < r1 * r2 * r3:
ans = r1 * r2 * r3
# 두 번째 경우: 전체 직사각형을 가로로만 분할한 경우
for i in range(1, n-1):
for j in range(i+1, n):
r1 = sum_cal(1, 1, i, m)
r2 = sum_cal(i+1, 1, j, m)
r3 = sum_cal(j+1, 1, n, m)
if ans < r1 * r2 * r3:
ans = r1 * r2 * r3
# 세 번째 경우: 전체 세로 분할 후 우측 가로 분할한 경우
for i in range(1, m):
for j in range(1, n):
r1 = sum_cal(1, 1, n, i)
r2 = sum_cal(1, i+1, j, m)
r3 = sum_cal(j+1, i+1, n, m)
if ans < r1 * r2 * r3:
ans = r1 * r2 * r3
# 네 번째 경우: 전체 세로 분할 후 좌측 가로 분할한 경우
for i in range(1, n):
for j in range(1, m):
r1 = sum_cal(1, 1, i, j)
r2 = sum_cal(i+1, 1, n, j)
r3 = sum_cal(1, j+1, n, m)
if ans < r1 * r2 * r3:
ans = r1 * r2 * r3
# 다섯번 째 경우: 전체 가로 분할 후 하단 세로 분할한 경우
for i in range(1, n):
for j in range(1, m):
r1 = sum_cal(1, 1, i, m)
r2 = sum_cal(i+1, 1, n, j)
r3 = sum_cal(i+1, j+1, n, m)
if ans < r1 * r2 * r3:
ans = r1 * r2 * r3
# 여섯번 째 경우: 전체 가로 분할 후 상단 세로 분할한 경우
for i in range(1, n):
for j in range(1, m):
r1 = sum_cal(1, 1, i, j)
r2 = sum_cal(1, j+1, i, m)
r3 = sum_cal(i+1, 1, n, m)
if ans < r1 * r2 * r3:
ans = r1 * r2 * r3
print(ans)
문제 해결
브루트포스 문제이다, 최대한 많은 조건을 꼼꼼히 나눠서 모든 주어진 문제를 해결해야한다.3개의 작은 직사각형으로 만드는 모든 조건을 6가지로 나눠서 세주었다. 자세한 설명은 코드에 주석을 달아 놨으니 참고하면 될것 같다.
반응형
'Problem Solving > 백준' 카테고리의 다른 글
[백준] 1463번 : 1로 만들기 - [Python/파이썬] (0) | 2023.04.13 |
---|---|
[백준] 1456번 : 거의 소수 - [Python/파이썬] (0) | 2023.04.12 |
[백준] 1448번: 삼각형 만들기 - [Python/파이썬] (0) | 2023.04.12 |
[백준] 1417번 : 국회의원 선거 - [Python/파이썬] (0) | 2023.04.12 |
[백준] 1406번: 에디터 - [Python/파이썬] (0) | 2023.04.12 |