BOJ 5826 Figure Eight
BOJ 5826 Figure Eight
문제 내용
크기의 사각 격자가 주어집니다. 격자의 각 칸은 . 또는 *입니다.
*인 칸들을 피해서 숫자 8을 그리려고 합니다. 이 숫자가 가져야 하는 특징은 다음과 같습니다.
- 숫자 8은 두 개의 직사각형을 위아래로 붙인 모양입니다.
- 두 직사각형은 모두 적어도 한 개의 칸을 내부에 포함합니다.
- 위쪽 직사각형의 아랫변은 아래쪽 직사각형의 윗변에 완전히 포함되어야 합니다.
- 두 직사각형의 테두리 위에
*가 한 개도 있으면 안됩니다. 직사각형의 내부에 있는 것은 상관 없습니다.
숫자 8을 그렸을 때의 점수는 두 직사각형 내부의 칸의 개수의 곱으로 정의합니다.
주어진 사각 격자에서 숫자 8을 하나 그려서 얻을 수 있는 최대 점수를 구하세요.
입력
첫 줄에는 이 주어집니다. ()
다음 줄에 걸쳐서 사각 격자가 공백 없이 주어집니다.
출력
문제의 정답을 출력합니다. 숫자 8을 그리는 방법 자체가 존재하지 않는다면 -1을 대신 출력합니다.
문제 풀이
스포일러
다음과 같은 브루트포스를 구상할 수 있습니다.
- 두 직사각형이 공유하는 가로줄의 번호 을 고릅니다.
- 가능한 왼쪽과 오른쪽 세로줄 번호의 쌍 에 대해, 왼쪽 변이 세로줄 위에 있고 오른쪽 변이 세로줄 위에 있는 위쪽 직사각형과 아래쪽 직사각형의 최대 면적을 각각 구합니다.
- 위쪽 직사각형들에 대해서 구간 DP를 하여 에 들어오는 모든 위쪽 직사각형 중 최대 면적을 구하고, 아래쪽 직사각형의 면적을 곱하여 아래쪽 직사각형의 가로 구간이 일 때의 최대 점수를 구합니다.
세 번째 과정의 시간 복잡도는 입니다. 두 번째 과정도 이 시간 복잡도에 맞추고 싶은데, 어떤 방향으로 스위핑을 하더라도 보다 빠르게 하기 어려워 보입니다.
여기서는 비트셋을 사용할 수 있습니다. 을 고정하고 을 오른쪽으로 움직이는 스위핑을 한다고 하면, 다음과 같이 할 수 있습니다.
- 각 세로줄 에 대해, 번째 세로줄에서
.인 가로줄들의 번호의 위치가 1인 비트셋 를 전처리해 둡니다. - 또한, 현재 가로줄 에 대해, 각 세로줄 에서 번째 가로줄을 포함하는 연속한
.의 영역이 1인 비트셋 를 만들어 둡니다. - 먼저 번째 세로줄에서, 을 가져오고, 을 AND합니다.
- 을 부터 시작하여 번째 가로줄에서
*를 만나거나 줄 끝에 닿을 때까지 다음을 반복합니다.- 을 AND하여 유지합니다. 현재 비트셋은 부터 까지를 완전히 이을 수 있는 가로줄들의 집합입니다.
- 이 집합에 을 AND한 결과의 최하위 비트와 최상위 비트의 위치를 확인합니다. 최하위 비트의 위치가 보다 작으면, 위쪽 직사각형의 최대 면적을 얻을 수 있습니다. 마찬가지로 최상위 비트의 위치가 보다 크면, 아래쪽 직사각형의 최대 면적을 얻을 수 있습니다.
Last updated on