728x90
문제
https://www.acmicpc.net/problem/14500
폴리오미노란 크기가 1×1인 정사각형을 여러 개 이어서 붙인 도형이며, 다음과 같은 조건을 만족해야 한다.
- 정사각형은 서로 겹치면 안 된다.
- 도형은 모두 연결되어 있어야 한다.
- 정사각형의 변끼리 연결되어 있어야 한다. 즉, 꼭짓점과 꼭짓점만 맞닿아 있으면 안 된다.
정사각형 4개를 이어 붙인 폴리오미노는 테트로미노라고 하며, 다음과 같은 5가지가 있다.
아름이는 크기가 N×M인 종이 위에 테트로미노 하나를 놓으려고 한다. 종이는 1×1 크기의 칸으로 나누어져 있으며, 각각의 칸에는 정수가 하나 쓰여 있다.
테트로미노 하나를 적절히 놓아서 테트로미노가 놓인 칸에 쓰여 있는 수들의 합을 최대로 하는 프로그램을 작성하시오.
테트로미노는 반드시 한 정사각형이 정확히 하나의 칸을 포함하도록 놓아야 하며, 회전이나 대칭을 시켜도 된다.
[ 입력 ]
첫째 줄에 종이의 세로 크기 N과 가로 크기 M이 주어진다. (4 ≤ N, M ≤ 500)
둘째 줄부터 N개의 줄에 종이에 쓰여 있는 수가 주어진다. i번째 줄의 j번째 수는 위에서부터 i번째 칸, 왼쪽에서부터 j번째 칸에 쓰여 있는 수이다. 입력으로 주어지는 수는 1,000을 넘지 않는 자연수이다.
[ 출력 ]
첫째 줄에 테트로미노가 놓인 칸에 쓰인 수들의 합의 최댓값을 출력한다.
풀이
- 모든 위치에서 출발하는 경우를 계산해서 최대값 구하기 / dfs 이용
- ㅗ 모양일 때를 주의해서 풀이
// 백준 - 테트로미노(14500)
import java.io.BufferedReader
import java.io.InputStreamReader
import java.util.StringTokenizer
import kotlin.math.max
val dx = arrayOf(1, -1, 0, 0)
val dy = arrayOf(0, 0, 1, -1)
var N = 0
var M = 0
var maxSum = 0
var paper: Array<Array<Int>> = arrayOf()
var visited: Array<Array<Boolean>> = arrayOf()
fun main() {
val br = BufferedReader(InputStreamReader(System.`in`))
var st = StringTokenizer(br.readLine())
N = st.nextToken().toInt()
M = st.nextToken().toInt()
paper = Array(N, {Array(M, {0})})
visited = Array(N, {Array(M, {false})})
for(i: Int in 0..N-1) {
st = StringTokenizer(br.readLine())
for(j: Int in 0..M-1) {
paper[i][j] = st.nextToken().toInt()
}
}
// 모든 지점에서 출발해보기
for(i: Int in 0..N-1) {
for(j: Int in 0..M-1) {
visited[i][j] = true
maxTetromino(i, j, paper[i][j], 1)
visited[i][j] = false
}
}
print(maxSum)
}
// 상하좌우 움직임으로 4개 정사각형 합 찾기
fun maxTetromino(x: Int, y: Int, sum: Int, cnt: Int) {
// 테트로미노 완성
if(cnt == 4) {
maxSum = max(sum, maxSum) // 최대값 구하기
return
}
for(i: Int in 0..3) {
val moveX = x + dx[i]
val moveY = y + dy[i]
// 범위 벗어나면 패스
if(moveX < 0 || moveX >= N || moveY < 0 || moveY >= M) continue
// 현재 조합 중인 테트로미노 조각에 포함되지 않은 경우
if(!visited[moveX][moveY]) {
// ㅗ, ㅜ, ㅏ, ㅓ 모양 테트로미노는 중간에 양쪽으로 갈리기 때문에
// 중간에 현재 위치에서 다른 방향으로 이동하도록
if(cnt == 2) {
visited[moveX][moveY] = true
maxTetromino(x, y, sum + paper[moveX][moveY], cnt + 1)
visited[moveX][moveY] = false
}
visited[moveX][moveY] = true
maxTetromino(moveX, moveY, sum + paper[moveX][moveY], cnt + 1)
visited[moveX][moveY] = false
}
}
}
+) 약 1년 전에 Java로 풀었던 코드가 있어서 함께 첨부 / 풀이 방법은 동일하다
// 백준 - 테트로미노(14500)
import java.io.IOException;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.StringTokenizer;
public class Main {
static int N, M;
static int[][] paper;
static boolean[][] visited;
static int max = 0; // 최대값 저장
// 상하좌우 이동
static int[] dx = {-1, 1, 0, 0};
static int[] dy = {0, 0, -1, 1};
public static void main(String[] args) throws IOException {
BufferedReader bf = new BufferedReader(new InputStreamReader(System.in));
StringTokenizer st = new StringTokenizer(bf.readLine());
N = Integer.parseInt(st.nextToken());
M = Integer.parseInt(st.nextToken());
paper = new int[N][M];
visited = new boolean[N][M];
// 입력
for(int i = 0; i < N; i++) {
st = new StringTokenizer(bf.readLine());
for(int j = 0; j < M; j++) {
paper[i][j] = Integer.parseInt(st.nextToken());
}
}
// 모든 경우의 수 계산
for(int i = 0; i < N; i++) {
for(int j = 0; j < M; j++) {
visited[i][j]= true;
maxTetromino(i, j, paper[i][j], 1);
visited[i][j] = false;
}
}
System.out.print(max);
}
// 상하좌우 움직임으로 4개 합 찾기
static void maxTetromino(int x, int y, int sum, int cnt){
// 테트로미노 모양 완성
if(cnt == 4) {
max = Math.max(sum, max);
return;
}
// 상하좌우 탐색
for(int i = 0; i < 4; i++) {
int moveX = x + dx[i];
int moveY = y + dy[i];
// 범위 벗어나는지 확인 = 벗어나면 패스
if(moveX < 0 || moveX >= N || moveY < 0 || moveY >= M) {
continue;
}
// 방문하지 않았는지 체크
if(!visited[moveX][moveY]) {
// ㅗ 모양 테트로미노는 중간에 양쪽으로 갈리기 때문에 한 번 더 체크
if(cnt == 2) {
visited[moveX][moveY] = true;
maxTetromino(x, y, sum + paper[moveX][moveY], cnt + 1); // 이동 후 위치 말고 현 위치로 전달
visited[moveX][moveY] = false;
}
visited[moveX][moveY] = true;
maxTetromino(moveX, moveY, sum + paper[moveX][moveY], cnt + 1);
visited[moveX][moveY] = false;
}
}
}
}
728x90
'Programming > Kotlin' 카테고리의 다른 글
[백준/Kotlin] 줄 세우기(2252) (0) | 2024.05.09 |
---|---|
[백준/Kotlin] 하늘에서 별똥별이 빗발친다(14658) (0) | 2024.05.09 |
[백준/Kotlin] 불(5427) (0) | 2024.05.07 |
[백준/Kotlin] 알약(4811) (0) | 2024.05.06 |
[백준/Kotlin] 욕심쟁이 판다(1937) (1) | 2024.05.06 |