문제
폴리오미노란 크기가 1×1인 정사각형을 여러 개 이어서 붙인 도형이며, 다음과 같은 조건을 만족해야 한다.
- 정사각형은 서로 겹치면 안 된다.
- 도형은 모두 연결되어 있어야 한다.
- 정사각형의 변끼리 연결되어 있어야 한다. 즉, 꼭짓점과 꼭짓점만 맞닿아 있으면 안 된다.
정사각형 4개를 이어 붙인 폴리오미노는 테트로미노라고 하며, 다음과 같은 5가지가 있다.
아름이는 크기가 N×M인 종이 위에 테트로미노 하나를 놓으려고 한다. 종이는 1×1 크기의 칸으로 나누어져 있으며, 각각의 칸에는 정수가 하나 쓰여 있다.
테트로미노 하나를 적절히 놓아서 테트로미노가 놓인 칸에 쓰여 있는 수들의 합을 최대로 하는 프로그램을 작성하시오.
테트로미노는 반드시 한 정사각형이 정확히 하나의 칸을 포함하도록 놓아야 하며, 회전이나 대칭을 시켜도 된다.
풀이
우선 모양이 5개지만 대칭이 가능하기 때문에, 대칭이 다른 도형 두개를 더추가하면 총 7개 도형이 존재한다.
static int[][][] shape = { {{0,0}, {0,1}, {0,2}, {0,3}},
{{0,0}, {0,1}, {1,0}, {1,1}},
{{0,0}, {1,0}, {2,0}, {2,1}},
{{0,0}, {1,0}, {2,0}, {2, -1}},
{{0,0}, {1,0}, {1,1}, {2,1}},
{{0,0}, {1,0}, {1,-1}, {2,-1}},
{{0,0}, {0,1}, {1,1}, {0,2}}};
미리 도형을 만들어 놓고 시작을 하였다.
도형을 돌리는건 맵전체를 돌려 구현하였다.
이때, 주의 할점은 가로 세로 길이가 다르기 때문에 맵의 방향에 따라 가로 세로를 바꿔주어야 한다.
static void turningMap() {
for(int t = 1; t < 4 ; t++) {
if(t % 2 == 1) {
for(int i = 0 ; i < N ; i++) {
for(int j = 0 ; j < M ; j++) {
map[t][M - 1 - j][i] = map[t - 1][i][j];
}
}
}
else {
for(int i = 0 ; i < M ; i++) {
for(int j = 0 ; j < N ; j++) {
map[t][N - 1 - j][i] = map[t - 1][i][j];
}
}
}
}
}
맵을 반시계 방향으로 돌려 총 4개를 미리 저장하였다.
이렇게 저장을 하고 완전탐색으로 모든 위치에 따라 점수합을 구해 최대값을 구하면 된다.
<전체코드>
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.PriorityQueue;
import java.util.Queue;
import java.util.Stack;
import java.util.StringTokenizer;
public class Main {
static int[][][] shape = { {{0,0}, {0,1}, {0,2}, {0,3}},
{{0,0}, {0,1}, {1,0}, {1,1}},
{{0,0}, {1,0}, {2,0}, {2,1}},
{{0,0}, {1,0}, {2,0}, {2, -1}},
{{0,0}, {1,0}, {1,1}, {2,1}},
{{0,0}, {1,0}, {1,-1}, {2,-1}},
{{0,0}, {0,1}, {1,1}, {0,2}}};
static int N, M;
static int[][][] map;
static int answer;
public static int parseInt(String string) {
return Integer.parseInt(string);
}
public static void main(String[] args) throws IOException{
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
StringTokenizer st = new StringTokenizer(br.readLine());
N = parseInt(st.nextToken());
M = parseInt(st.nextToken());
int big = Math.max(N, M);
map = new int[4][big][big];
for(int i = 0 ; i < N ; i++) {
st = new StringTokenizer(br.readLine());
for(int j = 0 ; j < M ; j++) {
map[0][i][j] = parseInt(st.nextToken());
}
}
turningMap();
//print();
answer = Integer.MIN_VALUE;
for(int i = 0 ; i < 7 ; i++) {
solution(i);
}
System.out.println(answer);
}
static void print() {
for(int t = 0; t < 4 ; t++) {
System.out.println("shape : " + t);
if(t % 2 == 0) {
for(int i = 0 ; i < N ; i++) {
for(int j = 0 ; j < M ; j++) {
System.out.print(map[t][i][j] + " ");
}
System.out.println();
}
}
else {
for(int i = 0 ; i < M ; i++) {
for(int j = 0 ; j < N ; j++) {
System.out.print(map[t][i][j] + " ");
}
System.out.println();
}
}
}
}
static void turningMap() {
for(int t = 1; t < 4 ; t++) {
if(t % 2 == 1) {
for(int i = 0 ; i < N ; i++) {
for(int j = 0 ; j < M ; j++) {
map[t][M - 1 - j][i] = map[t - 1][i][j];
}
}
}
else {
for(int i = 0 ; i < M ; i++) {
for(int j = 0 ; j < N ; j++) {
map[t][N - 1 - j][i] = map[t - 1][i][j];
}
}
}
}
}
static int getScore(int[][] nowMap, int r, int c, int s, int t) {
int sum = 0;
for(int i = 0 ; i < 4 ; i++) {
int nr = r + shape[s][i][0];
int nc = c + shape[s][i][1];
if(t % 2 == 0) {
if(nr < 0 || nr >= N || nc < 0 || nc >= M) { return -1; }
}
else {
if(nr < 0 || nr >= M || nc < 0 || nc >= N) { return -1;}
}
sum += nowMap[nr][nc];
}
return sum;
}
static void solution(int s) {
for(int t = 0 ; t < 4 ; t++) {
if(t % 2 == 0) {
for(int i = 0 ; i < N ; i++) {
for(int j = 0 ; j < M ; j++) {
int score = getScore(map[t], i, j, s, t);
answer = Math.max(answer, score);
}
}
}
else {
for(int i = 0 ; i < M ; i++) {
for(int j = 0 ; j < N ; j++) {
int score = getScore(map[t], i, j, s, t);
if(score < 0) {continue;}
answer = Math.max(answer, score);
}
}
}
}
}
}
'알고리즘 공부 > 구현 , 시뮬레이션' 카테고리의 다른 글
[백준] 10830 행렬 제곱 <Java> (0) | 2021.12.13 |
---|---|
[백준] 14890 경사로 (0) | 2021.10.23 |
[백준] 15684 사다리 조작 (0) | 2021.10.21 |
[백준] 17144 미세먼지 안녕! (0) | 2021.10.21 |
[백준] 17140 이차원 배열과 연산 (0) | 2021.10.20 |