일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | ||||
4 | 5 | 6 | 7 | 8 | 9 | 10 |
11 | 12 | 13 | 14 | 15 | 16 | 17 |
18 | 19 | 20 | 21 | 22 | 23 | 24 |
25 | 26 | 27 | 28 | 29 | 30 | 31 |
- 패스트파이브
- media3
- 재밌긴함
- 백준
- 패파
- parentfragment
- childfragment
- 안드로이드
- 파이썬
- 내부프레그먼트
- Stack
- 중첩네비게이션
- Android
- 공유오피스
- fragmentcontainer
- 자바
- media3 transformer
- 싱글액티비티
- innernavigation
- 스택
- SAA
- 코틀린
- MVVM
- 알고리즘
- 후기
- rxandroid
- Kotlin
- 사무실
- 아키텍쳐
- 너무 어렵다
삽질도사
[백준] 15683 감시 삼성 SW 역량 테스트 기출 문제 본문
https://www.acmicpc.net/problem/15683
15683번: 감시
스타트링크의 사무실은 1×1크기의 정사각형으로 나누어져 있는 N×M 크기의 직사각형으로 나타낼 수 있다. 사무실에는 총 K개의 CCTV가 설치되어져 있는데, CCTV는 5가지 종류가 있다. 각 CCTV가 감
www.acmicpc.net
후기 : 골드 4 수준은 절대 아닙니다~ 제 생각엔 골드 1정도. 문제 자체도 카메라가 많아서 솔직히 좀 지저분한 문제라는 생각이 들고 코드량도 많아지기 때문. 더군다나 중복체크를 허용하는 백트랙킹을 3번씩하는 것은 구현하거나 생각해내기가 상당히 어려웠다는 점에서 난이도도 있고 배울 점도 있었지만 딱~히 교육적인 문제라는 생각은 안드는 문제. (삼성에서 이런 비효울적인 문제를 테스트로 내는 이유는 뭘까...?) 풀면서 제일 크게 느낀 점은 카메라 갯수 좀 줄였으면 꽤 괜찮은 문제였을텐데.... 였음 -> 아~ 그렇구나 하고 넘어가는게 낫지 용써서 풀만한 문제는 아닌듯. 영양가x
풀이 : 백트랙킹으로 모든 카메라를 3번씩 체크하는 방식 사용.
ex) 1번 카메라 0번 돌리고 범위체크 -> 1번 카메라 1번 돌리고 범위체크 -> ..... -> 1번 카메라 3번 돌리고 2번 카메라 0번 돌리고 범위체크 -> 반복.
풀고나서 확인해보니 다른 분들은 dfs나 다른 방법으로 푸는 것으로 보이는데, 제가 좀 특이한듯.. 선호하는 방식으로 푸시면 될듯.
dfs 또한 카메라를 순회하면서 모든 카메라에 대해 탐색을 시도할 때 for문(4방향)을 넣어서 전체탐색하는 듯.
결론적으론 백트랙킹이랑 똑같음.
package backtracking.b15683_point_hardest
import java.util.LinkedList
val br = System.`in`.bufferedReader()
val getLine get() = br.readLine().split(" ").map { it.toInt() }
var yy = 0
var xx = 0
lateinit var map : Array<IntArray>
lateinit var cam : IntArray
val camQue = LinkedList<C>()
data class C(
val y:Int,
val x:Int,
val type: Int
)
fun isRange(y:Int,x:Int) = y in 0 until yy && x in 0 until xx
var res = Int.MAX_VALUE
fun move(m: Array<IntArray>, dir:Int, sy:Int, sx:Int){
var dy = sy
var dx = sx
when(dir){
0 -> while (true){
dy -= 1
if (!isRange(dy, dx) || m[dy][dx] == 6) break
m[dy][dx] = -1
}
1 -> while (true) {
dx += 1
if (!isRange(dy, dx) || m[dy][dx] == 6) break
m[dy][dx] = -1
}
2 -> while (true) {
dy += 1
if (!isRange(dy, dx) || m[dy][dx] == 6) break
m[dy][dx] = -1
}
3 -> while (true) {
dx -= 1
if (!isRange(dy, dx) || m[dy][dx] == 6) break
m[dy][dx] = -1
}
}
}
fun cal(): Int {
val m = Array(yy){IntArray(xx)}
for(y in 0 until yy)
for(x in 0 until xx) m[y][x] = map[y][x]
for(c in camQue){
val (cy,cx,ct) = c
m[cy][cx] = -1
val idx = cy*xx+cx
when(ct){
1 -> move(m,(cam[idx]+1)%4,cy,cx)
2 -> if(cam[idx]%2 == 0) {
move(m, 1, cy, cx)
move(m, 3, cy, cx)
} else {
move(m, 0, cy, cx)
move(m, 2, cy, cx)
}
3 -> {
move(m, cam[idx], cy,cx)
move(m, (cam[idx]+1)%4, cy,cx)
}
4 -> {
move(m,if(cam[idx]-1 == -1) 3 else cam[idx]-1,cy,cx)
move(m,cam[idx],cy,cx)
move(m,(cam[idx]+1)%4,cy,cx)
}
5 -> for(r in 0..3) move(m,r,cy,cx)
}
}
var cnt = 0
for(y in 0 until yy)
for(x in 0 until xx) if(m[y][x] == -1 || m[y][x] == 6) cnt++
return yy*xx-cnt
}
fun rotateCam(idx: Int){ // todo 3이 최대일 경우 -> 00 10 20 30 31 32 33 21 22 23 11 12 13 01 02 03 처럼 3번씩 고르는 모든 경우를 백트랙킹. (기존 백트랙킹과 비슷하지만 다른 방식으로 활용)
res = minOf(res,cal())
for(r in idx until yy*xx){
val y = r/xx //todo 2차원 배열을 1차원으로 변환할 때 y,x 좌표 모두 x좌표를 활용하여 구할 수 있다.
val x = r%xx
if(map[y][x] in 1..5 && cam[r] < 3){
cam[r]++
rotateCam(r)
cam[r]--
}
}
}
fun main(){
getLine.let {
yy = it[0]
xx = it[1]
map = Array(yy){ IntArray(xx) }
cam = IntArray(yy*xx)
for(y in 0 until yy){
val p = getLine
for(x in 0 until xx) {
if(p[x] in 1..5) camQue.add(C(y,x,p[x]))
map[y][x] = p[x]
}
}
rotateCam(0)
println(res)
}
}
'백준' 카테고리의 다른 글
[백준] 1113번 수영장만들기 코틀린 (0) | 2024.02.08 |
---|---|
[백준] 2504 괄호의 값 자바 (0) | 2021.12.28 |
[백준] 10799 쇠막대기 자바 (0) | 2021.12.27 |
[백준] 빗물 14719 자바 (0) | 2021.03.24 |
[백준] 달력 20207 자바 (0) | 2021.03.23 |