관리 메뉴

코딩하는 락커

[BOJ 3085] 사탕게임 (Go 풀이) 본문

💯 코딩테스트/[2021~] 💯 코딩테스트

[BOJ 3085] 사탕게임 (Go 풀이)

락꿈사 2025. 10. 19. 18:17

상근이는 어렸을 적에 "봄보니 (Bomboni)" 게임을 즐겨했다.

가장 처음에 N×N크기에 사탕을 채워 놓는다. 사탕의 색은 모두 같지 않을 수도 있다. 상근이는 사탕의 색이 다른 인접한 두 칸을 고른다. 그 다음 고른 칸에 들어있는 사탕을 서로 교환한다. 이제, 모두 같은 색으로 이루어져 있는 가장 긴 연속 부분(행 또는 열)을 고른 다음 그 사탕을 모두 먹는다.

사탕이 채워진 상태가 주어졌을 때, 상근이가 먹을 수 있는 사탕의 최대 개수를 구하는 프로그램을 작성하시오.

입력

 

첫째 줄에 보드의 크기 N이 주어진다. (3 ≤ N ≤ 50)

다음 N개 줄에는 보드에 채워져 있는 사탕의 색상이 주어진다. 빨간색은 C, 파란색은 P, 초록색은 Z, 노란색은 Y로 주어진다.

사탕의 색이 다른 인접한 두 칸이 존재하는 입력만 주어진다.

출력

첫째 줄에 상근이가 먹을 수 있는 사탕의 최대 개수를 출력한다.

코드

package main

import (
	"bufio"
	"fmt"
	"os"
)

func check(x, y, n int) bool {
	return x >= 0 && x < n && y >= 0 && y < n
}

func swith(x, y, newX, newY int, arr [][]byte) {
	arr[x][y], arr[newX][newY] = arr[newX][newY], arr[x][y]
}

func count(arr [][]byte, n int) int {
	maxCount := 1

	for i := 0; i < n; i++ {
		curr := arr[i][0]
		count := 1
		for j := 1; j < n; j++ {
			if arr[i][j] != curr {
				curr = arr[i][j]
				count = 1
			} else {
				count++
				if count > maxCount {
					maxCount = count
				}
			}
		}
	}

	for j := 0; j < n; j++ {
		curr := arr[0][j]
		count := 1
		for i := 1; i < n; i++ {
			if arr[i][j] != curr {
				curr = arr[i][j]
				count = 1
			} else {
				count++
				if count > maxCount {
					maxCount = count
				}
			}
		}
	}

	return maxCount
}

func main() {
	reader := bufio.NewReader(os.Stdin)
	writer := bufio.NewWriter(os.Stdout)
	defer writer.Flush()

	var n int
	fmt.Fscan(reader, &n)

	arr := make([][]byte, n)
	for i := 0; i < n; i++ {
		var s string
		fmt.Fscan(reader, &s)
		arr[i] = []byte(s)
	}

	maxCount := 1
	dx := []int{1, 0}
	dy := []int{0, 1}

	for i := 0; i < n; i++ {
		for j := 0; j < n; j++ {
			for k := 0; k < 2; k++ {
				newX := i + dx[k]
				newY := j + dy[k]
				if !check(newX, newY, n) {
					continue
				}
				if arr[i][j] == arr[newX][newY] {
					continue
				}
				swith(i, j, newX, newY, arr)
				cnt := count(arr, n)
				if cnt > maxCount {
					maxCount = cnt
				}
				swith(i, j, newX, newY, arr)
			}
		}
	}

	fmt.Fprint(writer, maxCount)
}

 

풀이

로직은 아래와 같다.
1. 모든 칸 (i, j) 에 대해 인접한 칸 (i+1, j), (i, j+1) 과 스왑 시도. 이 때 사방면을 모두 체크하면 중복되므로 오른쪽과 아래만 확인한다. 
2. 스왑 후 전체 보드에서 가로로 연속된 같은 색 사탕의 최대길이와 세로로 연속된 사탕의 최대 길이를 계산한다

3. 2에서 계산한 값으로 최대 값을 갱신한다

4. 다시 원상복구하고 다음 칸으로 이동한다.

 

재미로 Go 공부할 겸 ~ Python으로 2년 전에 풀었던 문제를 Go로도 풀어보았다. 

메모리 1000kb에 20ms 밖에 안걸리다니 ㄷㄷ ... go 진짜 엄청 빠르구나 ... 그치만 파이썬에 비해서 코드가 길어지는 건 족금 ... ^^;

 

Comments