こんにちは、ナナオです。

前回に引き続き競プロを実施していきたいと思います。

今回の問題は以下です。

リバーシの操作(縦横) | レベルアップ問題集 | プログラミング学習サイト【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]))
    }
}

前回からキューを活用した実装になりがちですね。

一応解説を見ましたが、キューを使わずに石が見つかった段階でもう一段階ループするような実装になっていました。

個人的にはキューを使ったほうがすっきりするので好きですね。たぶんメモリ効率変わらんし…(キュー保持する分多少悪いかな?)

👍