-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #240 from wellFoundedDevelopers/hyunsoo/58week
[전현수] - 양치기 꿍, 술래 잡기
- Loading branch information
Showing
4 changed files
with
1,065 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,220 @@ | ||
package hyunsoo.`58week` | ||
|
||
import java.util.Stack | ||
import kotlin.math.absoluteValue | ||
|
||
/** | ||
* | ||
* <문제> | ||
* [술래 잡기](https://www.codetree.ai/training-field/frequent-problems/problems/hide-and-seek/description?page=1&pageSize=20) | ||
* | ||
* - 아이디어 | ||
* | ||
* - 트러블 슈팅 | ||
* | ||
*/ | ||
class `전현수_술래_잡기` { | ||
|
||
data class Position(val x: Int, val y: Int) { | ||
|
||
operator fun plus(other: Position): Position { | ||
return Position(x + other.x, y + other.y) | ||
} | ||
|
||
operator fun minus(other: Position): Position { | ||
return Position(x - other.x, y - other.y) | ||
} | ||
|
||
operator fun times(cnt: Int): Position { | ||
return Position(x * cnt, y * cnt) | ||
} | ||
|
||
fun diff(other: Position): Int { | ||
return (this.x - other.x).absoluteValue + (this.y - other.y).absoluteValue | ||
} | ||
} | ||
|
||
private data class Fugitive(val pos: Position, val orientation: FugitiveDirs) | ||
|
||
private val fugitiveList = mutableListOf<Fugitive?>() | ||
|
||
private val treeList = mutableListOf<Position>() | ||
|
||
private val dirs = listOf( | ||
Position(-1, 0), | ||
Position(0, 1), | ||
Position(1, 0), | ||
Position(0, -1) | ||
) | ||
|
||
enum class FugitiveDirs(val dir: Position) { | ||
UP(Position(-1, 0)), | ||
DOWN(Position(1, 0)), | ||
RIGHT(Position(0, 1)), | ||
LEFT(Position(0, -1)); | ||
|
||
fun change() = when (this) { | ||
UP -> DOWN | ||
DOWN -> UP | ||
LEFT -> RIGHT | ||
else -> LEFT | ||
} | ||
} | ||
|
||
fun solution() { | ||
|
||
val (size, fugitiveCnt, treeCnt, turnCnt) = readLine()!!.split(" ").map { it.toInt() } | ||
var totalScore = 0 | ||
|
||
var tagger = Position(size / 2, size / 2) | ||
var taggerDir = dirs.first() | ||
// 움직인 횟수 | ||
var taggerMoveCnt = 0 | ||
var criterionForCriterion = 0 | ||
var criterion = 1 | ||
var isForward = true | ||
|
||
repeat(fugitiveCnt) { | ||
val (x, y, dir) = readLine()!!.split(" ").map { it.toInt() } | ||
fugitiveList.add( | ||
Fugitive( | ||
Position(x - 1, y - 1), | ||
if (dir == 1) FugitiveDirs.RIGHT else FugitiveDirs.DOWN | ||
) | ||
) | ||
} | ||
|
||
repeat(treeCnt) { | ||
readLine()!!.split(" ").map { it.toInt() }.apply { | ||
treeList.add(Position(first() - 1, last() - 1)) | ||
} | ||
} | ||
|
||
repeat(turnCnt) { turnIndex -> | ||
|
||
// 도망자 이동 | ||
fugitiveList.forEachIndexed { fugIndex, curFug -> | ||
|
||
if (curFug == null) return@forEachIndexed | ||
|
||
val diff = curFug.pos.diff(tagger) | ||
if (4 <= diff) return@forEachIndexed | ||
|
||
val nextPos = curFug.pos + curFug.orientation.dir | ||
|
||
// 격자를 벗어나지 않는 경우 | ||
if (nextPos.x in 0 until size && | ||
nextPos.y in 0 until size | ||
) { | ||
// 다음 칸에 술래 여부 확인 | ||
if (nextPos == tagger) return@forEachIndexed | ||
|
||
fugitiveList[fugIndex] = curFug.copy(pos = nextPos) | ||
// 격자를 벗어나는 경우 | ||
} else { | ||
|
||
val rotatedCurFug = curFug.copy( | ||
orientation = curFug.orientation.change() | ||
) | ||
|
||
// 방향 전환 적용 | ||
fugitiveList[fugIndex] = rotatedCurFug | ||
|
||
val nextPos = rotatedCurFug.pos + rotatedCurFug.orientation.dir | ||
|
||
// 다음 칸에 술래 여부 확인 | ||
if (nextPos == tagger) return@forEachIndexed | ||
|
||
fugitiveList[fugIndex] = rotatedCurFug.copy(pos = nextPos) | ||
|
||
} | ||
} | ||
|
||
// 술래 이동 | ||
if (isForward) { | ||
tagger += taggerDir | ||
taggerMoveCnt++ | ||
|
||
// 기준치 만큼 움직였을 경우 방향 전환 | ||
if (taggerMoveCnt == criterion) { | ||
taggerDir = dirs[(dirs.indexOf(taggerDir) + 1) % 4] | ||
criterionForCriterion++ | ||
taggerMoveCnt = 0 | ||
} | ||
|
||
// 1 1, 2 2, 3 3 이런식으로 움직일 수 있도록 | ||
if (criterionForCriterion == 2) { | ||
criterion++ | ||
criterionForCriterion = 0 | ||
} | ||
|
||
if (tagger == Position(0, 0)) { | ||
isForward = false | ||
taggerDir = dirs[2] | ||
taggerMoveCnt = 0 | ||
} | ||
|
||
} else { | ||
tagger += taggerDir | ||
taggerMoveCnt++ | ||
|
||
// 처음 역방향 탐색 시 5 5 5, 4 4 이런식으로 움직여야함. | ||
if (tagger.x !in 0 until size || | ||
tagger.y !in 0 until size | ||
) { | ||
tagger -= taggerDir | ||
taggerDir = dirs[(dirs.indexOf(taggerDir) + 3) % 4] | ||
tagger += taggerDir | ||
taggerMoveCnt = 1 | ||
criterion-- | ||
} else { | ||
// 기준치 만큼 움직였을 경우 방향 전환 | ||
if (taggerMoveCnt == criterion) { | ||
taggerDir = dirs[(dirs.indexOf(taggerDir) + 3) % 4] | ||
criterionForCriterion++ | ||
taggerMoveCnt = 0 | ||
} | ||
|
||
if (criterionForCriterion == 2) { | ||
criterion-- | ||
criterionForCriterion = 0 | ||
} | ||
|
||
if (tagger == Position(size / 2, size / 2)) { | ||
isForward = true | ||
taggerDir = dirs.first() | ||
taggerMoveCnt = 0 | ||
criterion = 1 | ||
criterionForCriterion = 0 | ||
} | ||
} | ||
|
||
} | ||
|
||
val caughtFugitive = Stack<Int>() | ||
for (i in 0 until 3) { | ||
val nextPos = tagger + (taggerDir * i) | ||
if (nextPos in treeList) continue | ||
|
||
fugitiveList.forEachIndexed { index, fug -> | ||
if (fug?.pos == nextPos) caughtFugitive.add(index) | ||
} | ||
} | ||
|
||
while (caughtFugitive.isNotEmpty()) { | ||
val targetIndex = caughtFugitive.pop() | ||
fugitiveList[targetIndex] = null | ||
totalScore += turnIndex + 1 | ||
} | ||
|
||
} | ||
|
||
println(totalScore) | ||
} | ||
|
||
|
||
} | ||
|
||
fun main() { | ||
전현수_술래_잡기().solution() | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,122 @@ | ||
package hyunsoo.`58week` | ||
|
||
import java.util.LinkedList | ||
import java.util.Queue | ||
import java.util.Stack | ||
|
||
/** | ||
* | ||
* <문제> | ||
* [양치기 꿍](https://www.acmicpc.net/problem/3187) | ||
* | ||
* - 아이디어 | ||
* | ||
* - 트러블 슈팅 | ||
* | ||
*/ | ||
class `전현수_양치기_꿍` { | ||
|
||
private data class Position(val x: Int, val y: Int) | ||
|
||
private val dirs = listOf( | ||
Position(-1, 0), | ||
Position(1, 0), | ||
Position(0, 1), | ||
Position(0, -1), | ||
) | ||
|
||
private val board = mutableListOf<MutableList<String>>() | ||
|
||
fun solution() { | ||
|
||
val (r, c) = readln().split(" ").map { it.toInt() } | ||
|
||
val visited = Array(r) { | ||
BooleanArray(c) | ||
} | ||
|
||
repeat(r) { | ||
val row = readln().chunked(1) as MutableList | ||
board.add(row) | ||
} | ||
|
||
for (i in 0 until r) { | ||
for (j in 0 until c) { | ||
|
||
val cur = board[i][j] | ||
if (cur == WALL || cur == EMPTY) continue | ||
|
||
val sheepStack = Stack<Position>() | ||
val wolfStack = Stack<Position>() | ||
|
||
val queue: Queue<Position> = LinkedList() | ||
queue.add(Position(i, j)) | ||
|
||
investigate(queue, sheepStack, wolfStack, visited) | ||
|
||
if (wolfStack.size == 0 || sheepStack.size == 0) continue | ||
|
||
if (wolfStack.size < sheepStack.size) consume(wolfStack) | ||
else consume(sheepStack) | ||
|
||
} | ||
} | ||
|
||
val flattedBoard = board.flatten() | ||
println( | ||
"${flattedBoard.count { it == SHEEP }} ${flattedBoard.count { it == WOLF }}" | ||
) | ||
} | ||
|
||
private fun investigate( | ||
queue: Queue<Position>, | ||
sheepStack: Stack<Position>, | ||
wolfStack: Stack<Position>, | ||
visited: Array<BooleanArray>, | ||
) { | ||
while (queue.isNotEmpty()) { | ||
|
||
val curPos = queue.poll() | ||
val curInfo = board[curPos.x][curPos.y] | ||
|
||
if (visited[curPos.x][curPos.y]) continue | ||
visited[curPos.x][curPos.y] = true | ||
|
||
if (curInfo == WOLF) wolfStack.add(Position(curPos.x, curPos.y)) | ||
else if (curInfo == SHEEP) sheepStack.add(Position(curPos.x, curPos.y)) | ||
|
||
dirs.forEach { dir -> | ||
val nx = curPos.x + dir.x | ||
val ny = curPos.y + dir.y | ||
|
||
if (nx !in 0 until board.size || | ||
ny !in 0 until board.first().size || | ||
board[nx][ny] == WALL || | ||
visited[nx][ny] | ||
) return@forEach | ||
|
||
queue.add(Position(nx, ny)) | ||
} | ||
} | ||
} | ||
|
||
private fun consume(stack: Stack<Position>) { | ||
|
||
while (stack.isNotEmpty()) { | ||
val curPos = stack.pop() | ||
board[curPos.x][curPos.y] = "." | ||
} | ||
|
||
} | ||
|
||
companion object { | ||
const val WALL = "#" | ||
const val EMPTY = "." | ||
const val WOLF = "v" | ||
const val SHEEP = "k" | ||
} | ||
} | ||
|
||
fun main() { | ||
전현수_양치기_꿍().solution() | ||
} |
Oops, something went wrong.