こんにちは、ナナオです。
前回に引き続き競プロを実施していきたいと思います。
今回の問題は以下です。
リバーシの操作(縦横) | レベルアップ問題集 | プログラミング学習サイト【paizaラーニング】
実装
結構悩んだりAIと壁打ちしたりした結果、以下のような実装になりました。
package main
import "fmt"
func main(){
var h, w, y, x int
fmt.Scan(&h, &w, &y, &x)
g := make([][]rune, h)
for i := 0; i < h; i++ {
var s string
fmt.Scan(&s)
g[i] = []rune(s)
}
// 4方向でループする
dy := []int{1, -1, 0, 0}
dx := []int{0, 0, 1, -1}
// 置いた石のキュー
qy := []int{y}
qx := []int{x}
for i := 0; i < 4; i++ {
var ty, tx []int
// 壁に当たるまでループする
for j := 1;; j++ {
sy, sx := y + dy[i] * j, x + dx[i] * j
if sy >= 0 && sx >= 0 && sy < h && sx < w {
if g[sy][sx] == '*' {
qy = append(qy, ty...)
qx = append(qx, tx...)
break
} else {
ty = append(ty, sy)
tx = append(tx, sx)
}
} else {
break
}
}
}
// キューを消化
for len(qy) > 0 {
sy, sx := qy[0], qx[0]
qy, qx = qy[1:], qx[1:]
g[sy][sx] = '*'
}
for i := 0; i < h; i++ {
fmt.Println(string(g[i]))
}
}
前回からキューを活用した実装になりがちですね。
一応解説を見ましたが、キューを使わずに石が見つかった段階でもう一段階ループするような実装になっていました。
個人的にはキューを使ったほうがすっきりするので好きですね。たぶんメモリ効率変わらんし…(キュー保持する分多少悪いかな?)
👍