문제 >
폴리오미노란 크기가 1×1인 정사각형을 여러 개 이어서 붙인 도형이며, 다음과 같은 조건을 만족해야 한다.
- 정사각형은 서로 겹치면 안 된다.
- 도형은 모두 연결되어 있어야 한다.
- 정사각형의 변끼리 연결되어 있어야 한다. 즉, 꼭짓점과 꼭짓점만 맞닿아 있으면 안 된다.
정사각형 4개를 이어 붙인 폴리오미노는 테트로미노라고 하며, 다음과 같은 5가지가 있다.
아름이는 크기가 N×M인 종이 위에 테트로미노 하나를 놓으려고 한다. 종이는 1×1 크기의 칸으로 나누어져 있으며, 각각의 칸에는 정수가 하나 쓰여 있다.
테트로미노 하나를 적절히 놓아서 테트로미노가 놓인 칸에 쓰여 있는 수들의 합을 최대로 하는 프로그램을 작성하시오.
테트로미노는 반드시 한 정사각형이 정확히 하나의 칸을 포함하도록 놓아야 하며, 회전이나 대칭을 시켜도 된다.
입력 >
첫째 줄에 종이의 세로 크기 N과 가로 크기 M이 주어진다. (4 ≤ N, M ≤ 500)
둘째 줄부터 N개의 줄에 종이에 쓰여 있는 수가 주어진다. i번째 줄의 j번째 수는 위에서부터 i번째 칸, 왼쪽에서부터 j번째 칸에 쓰여 있는 수이다. 입력으로 주어지는 수는 1,000을 넘지 않는 자연수이다.
출력 >
첫째 줄에 테트로미노가 놓인 칸에 쓰인 수들의 합의 최댓값을 출력한다.
해결방법 >
DFS(깊이우선탐색)으로 한 정점에서 시작으로 4개의 정점을 방문하면 위의 도형의 모든 모양을 만들 수 있다고 생각했다.
그렇다고 생각했는데 3번째 예제의 답이 틀렸다.
그래서 방문한 정점의 모양을 출력해봤더니
이게 나오질 않았다. 그래서 BFS 함수를 하나 더만들어서 해줬더니 입력값이 커져버렸을 때, 시간초과가 발생해버렸다...
그래서 DFS로 구할 수 있는 도형은 모두 찾되, 나오지 않는 하나의 도형의 모양을 만들어주는 함수를 따로하나 만들어주었다.
[JAVA]
package baekjoon;
import java.util.*;
import java.io.*;
public class BOJ_14500 {
static int n;
static int m;
static int[][] map;
static int[][] visit;
static int[] dx = {-1, 0, 1, 0};
static int[] dy = {0, 1, 0, -1};
static int max;
static int[][] dir1 = {{0, 1}, {0, 2}, {1, 1}};
static int[][] dir2 = {{1, 0}, {2, 0}, {1, 1}};
static int[][] symm = {{1, 1}, {-1, 1}, {1, -1}, {-1, -1}};
public static void dfs(int x, int y, int depth, int sum) {
visit[x][y] = 1;
sum += map[x][y];
if(depth == 4) {
max = Math.max(sum, max);
visit[x][y] = 0;
return;
}
for(int i = 0; i < 4; i++) {
int nx = x + dx[i];
int ny = y + dy[i];
if(nx >= 0 && ny >= 0 && nx < n && ny < m && visit[nx][ny] == 0) {
dfs(nx, ny, depth+1, sum);
}
}
visit[x][y] = 0;
}
public static void shape(int x, int y) {
for(int i = 0; i < 4; i++) {
int sum = map[x][y];
for(int j = 0; j < 3; j++) {
int nx = x + symm[i][0] * dir1[j][0];
int ny = y + symm[i][1] * dir1[j][1];
if(nx >= 0 && ny >= 0 && nx < n && ny < m) {
sum += map[nx][ny];
}
else break;
}
max = Math.max(sum, max);
}
for(int i = 0; i < 4; i++) {
int sum = map[x][y];
for(int j = 0; j < 3; j++) {
int nx = x + symm[i][0] * dir2[j][0];
int ny = y + symm[i][1] * dir2[j][1];
if(nx >= 0 && ny >= 0 && nx < n && ny < m) {
sum += map[nx][ny];
}
else break;
}
max = Math.max(sum, max);
}
}
public static void main(String[] args) throws IOException{
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
StringTokenizer tk = new StringTokenizer(br.readLine());
n = Integer.parseInt(tk.nextToken());
m = Integer.parseInt(tk.nextToken());
map = new int[n][m];
visit = new int[n][m];
for(int i = 0; i < n; i++) {
tk = new StringTokenizer(br.readLine());
for(int j = 0; j < m; j++) {
map[i][j] = Integer.parseInt(tk.nextToken());
}
}
for(int i = 0; i < n; i++) {
for(int j = 0; j < m; j++) {
dfs(i, j, 1, 0);
shape(i, j);
}
}
System.out.println(max);
}
}
'Problem Solving > BOJ' 카테고리의 다른 글
[백준] 17822번 - 원판 돌리기 (0) | 2020.03.18 |
---|---|
[백준] 5373번 - 큐빙 (0) | 2020.03.16 |
[백준] 16234번 - 인구 이동 (0) | 2020.03.16 |
[백준] 14499번 - 주사위 굴리기 (0) | 2020.03.16 |
[백준] 16236번 - 아기 상어 (0) | 2020.03.16 |
댓글