[学習記録]AtCoder EDP H-Grid-1[Go]

問題

縦H 行、横 W 列のグリッドがあります。 上から i 行目、左から j 列目のマスを (i,j) で表します。

各 i,j (1≤i≤H, 1≤j≤W) について、マス (i,j) の情報が文字 ai,j​ によって与えられます。 ai,j​ が . ならばマス (i,j) は空マスであり、ai,j​ が # ならばマス (i,j) は壁のマスです。 マス (1,1)(1,1) および (H,W) は空マスであることが保証されています。

太郎君は、マス (1,1)(1,1) から出発し、右または下に隣り合う空マスへの移動を繰り返すことで、マス (H,W) まで辿り着こうとしています。

マス (1,1)(1,1) から (H,W) までの太郎君の経路は何通りでしょうか? 答えは非常に大きくなりうるので、10^9+7 で割った余りを求めてください。

解法

マス (i, j)に移動できるのは
・マス ( i -1, j) (上からの移動)
・マス ( i, j -1) (左からの移動)
のみとなっているので、各i, jについて上記を計算する。
壁の場合は通ることができないのでゼロになる

// あとで取り出しやすいようにスライスで保持
sli := make([][]string, h)
for i := 0; i < h; i++ {
	sli[i] = strings.Split(read(), "")
}

for i := 1; i <= h; i++ {
	dp[i] = make([]int, w+1)
	for j := 1; j <= w; j++ {
		if sli[i-1][j-1] == "." {
            // 道
     		dp[i][j] = (dp[i-1][j] + dp[i][j-1])
		} else {
            // 壁
			dp[i][j] = 0
		}
	}
}

マス(1, 1)は空マス確定であり、そこへ行く経路は1となる(dp[1][1] = 1)
そうなるように、dpに初期値を設定する
(dp[0][1]に1を設定することで、ループ内で分岐をせずとも各々の操作が可能になる)

dp := make([][]int, h+1)
dp[0] = make([]int, w+1)
dp[0][1] = 1

> (loop start)
> dp[1][1] = dp[0][1] + dp[1][0] = 1 + 0 = 1

出力は10 ^ 9 + 7で割ったあまりを出す必要がある。
そのため、dpに値を入れる時に余りをとる。
(最後に余りをとると、途中の計算時にオーバーフローしてしまう場合がある)

// 道
dp[i][j] = (dp[i-1][j] + dp[i][j-1]) % prime_number

コード(AC)

func run() interface{} {
	h, w := readInt(), readInt()

	sli := make([][]string, h)
	for i := 0; i < h; i++ {
		sli[i] = strings.Split(read(), "")
	}

	dp := make([][]int, h+1)
	dp[0] = make([]int, w+1)
	dp[0][1] = 1
	for i := 1; i <= h; i++ {
		dp[i] = make([]int, w+1)
		for j := 1; j <= w; j++ {
			if sli[i-1][j-1] == "." {
                // 道
				dp[i][j] = (dp[i-1][j] + dp[i][j-1]) % prime_number
			} else {
                // 壁
				dp[i][j] = 0
			}
		}
	}

	ans := dp[h][w]
	return ans
}

この記事が気に入ったらサポートをしてみませんか?