알고리즘 공부/구현 , 시뮬레이션

[백준] 14500 테트로미노

kdhoooon 2021. 10. 22. 00:32

문제

폴리오미노란 크기가 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);
					}
				}
			}
		}
		
	}
}