문제 링크: https://www.acmicpc.net/problem/28015
28015번: 영역 색칠
첫째 줄에는 그림의 세로 길이 $N$과 가로 길이 $M$이 공백으로 구분되어 주어진다. $(2\leq N,M\leq 100)$ 그다음 $N$줄에 걸쳐 $M$개의 정수가 공백으로 구분되어 주어진다. 각 정수는 그림 한 칸의 정보
www.acmicpc.net
고작 실버 3 따리 문제지만, 삽질을 하도 많이 해서 올려봅니다.
첫 번째 시도(틀렸습니다.)
package thirtyseventh
import java.io.*
fun main(){
val br = BufferedReader(InputStreamReader(System.`in`))
val (n,m) = br.readLine().split(' ').map{it.toInt()}
val arr = Array(n){Array(m){0} }
// 횟수를 저장할 dp 배열
val dp = Array(n){Array(m){0} }
repeat(n){
val list = br.readLine().split(' ').map{it.toInt()}
for (index in list.indices){
arr[it][index] = list[index]
}
}
for (index in 0 until n){
// 각 반복 때마다, 0번 째의 dp 배열을 초기화 해줍니다.
// 해당 영역의 값이 0이면 0, 1이나 2이면 한 번 칠한 것이므로 1로 저장합니다.
if (arr[index][0] != 0)
dp[index][0] = 1
for (index1 in 1 until m){
// 현재의 영역 값
val cur = arr[index][index1]
// 이전의 영역 값
val prev = arr[index][index1 - 1]
// 현재의 영역값이 0이면, 이전 dp 배열의 값을 그대로 저장합니다.
if (cur == 0){
dp[index][index1] = dp[index][index1-1]
}
// 0 이 아닐 때,
else{
// 현재 영역값이 이전 영역값과 다르면, 이전 dp 값의 +1을 저장
// 같을 경우, 이전 dp 배열의 값을 그대로 저장합니다.
if (cur != prev)
dp[index][index1] = dp[index][index1-1] + 1
else
dp[index][index1] = dp[index][index1-1]
}
}
}
// 각 dp 배열의 층마다 마지막 값을 모두 더합니다.
var count = 0
for (index in 0 until n){
count += dp[index][m-1]
}
println(count)
}
논리가 완벽하다 생각을 했습니다.
문제를 잘못 이해하고 있나 싶어서 다시 꼼꼼히 읽어봤습니다.
저 "덧칠이 가능하다."라는 문장이 눈에 띄었습니다.
만약 한 줄에 1 1 1 1 1 2 1 1 1 2라는 입력값이 들어왔을 경우,
첫 번째 풀이에서는 횟수를 4로 계산을 했습니다.
하지만 덧칠이 가능할 경우,
전체를 1로 칠하는 횟수 = 1
2 만 칠하는 횟수 = 2 로 총횟수가 3이 나옵니다.
논리를 수정해서 다시 코드를 작성하였습니다.
두 번째 시도 (맞았습니다.)
package thirtyseventh
import java.io.*
fun main(){
val br = BufferedReader(InputStreamReader(System.`in`))
val (n,m) = br.readLine().split(' ').map{it.toInt()}
val arr = Array(n){Array(m){0} }
val dp = Array(n){Array(m){0} }
repeat(n){
val list = br.readLine().split(' ').map{it.toInt()}
for (index in list.indices){
arr[it][index] = list[index]
}
}
for (index in 0 until n){
// 기준이 되는 변수를 만들었습니다.
// 각 줄마다 첫 번째 영역값이 0일 경우는 -1,
// 1과 2일 경우는 각 영역값을 저장합니다.
var first = -1
if (arr[index][0] != 0){
first = arr[index][0]
dp[index][0] = 1
}
for (index1 in 1 until m){
val cur = arr[index][index1]
val prev = arr[index][index1 - 1]
// 현재의 영역값이 0일 경우, first 변수에 -1을 저장합니다.
if (cur == 0){
dp[index][index1] = dp[index][index1-1]
first = -1
}
// 현재의 영역값이 0이 아닐 때
else{
// first 값이 -1일 경우, 이전 값이 0이라는 뜻이므로
// first 변수에 현재 영역값 저장,
// dp 배열의 이전의 값에 1을 더한 값을 저장합니다.
if (first == -1){
first = cur
dp[index][index1] = dp[index][index1-1] + 1
}
// first 값이 -1이 아닐 경우
else{
// 현재의 값이 first 값과 같을 경우
// 이전 값과 같은 경우이므로 dp 배열의 이전의 값을 그대로 저장
if (cur == first)
dp[index][index1] = dp[index][index1-1]
// 현재의 값이 first 값과 다를 경우
// ex) 1 1 1 1 2 2 1 2
// 저 가운데 2 2 부분은 한 붓으로 칠할 수 있다.
else{
// 현재의 값과 이전의 값이 다를 경우
// dp 이전 배열의 값에 +1 한 값을 저장
if (cur != prev)
dp[index][index1] = dp[index][index1-1] + 1
// 같을 경우 -> ex) 2 2
// dp 배열의 이전의 값을 그대로 저장
else
dp[index][index1] = dp[index][index1-1]
}
}
}
}
}
// dp 배열의 층마다 마지막 값을 더하기
var count = 0L
for (index in 0 until n){
count += dp[index][m-1]
}
println(count)
}
실버 3 문제중에 가장 어려웠던 것 같아요..
'알고리즘 > 매일마다 풀기(백준)' 카테고리의 다른 글
[2023-05-09] 24479 알고리즘 수업 - 깊이 우선 탐색 1 (Kotlin) + 7문제 (0) | 2023.05.09 |
---|---|
[2023-05-08] 1735 분수 합(Kotlin) + 4문제 (0) | 2023.05.08 |
[2023-05-06] 1890 점프 (Kotlin) + 6문제 (0) | 2023.05.06 |
[2023-05-05] 1325 효율적인 해킹 (Kotlin) + 5문제 (0) | 2023.05.05 |
[2023-05-04] 18111 마인크래프트 (Kotlin) + 9문제 (0) | 2023.05.04 |
댓글