典型90【050 – Stair Jump(★3)】をpython解説

Python

AtCoder の問題を解くために必要な実力を付けるために作られた「典型問題」を解いていく企画として、「典型90」があります。

今回は、その内、の50問目である「Stair Jump(★3)」を解説していきたいと思います。
なにか、間違っているところなどありましたら、@EitaSugiまで、ご指導ご鞭撻の程、よろしくお願い致します!

問題名 【050 – Stair Jump(★3)】

問題

考察

考えた内容の概要

この問題は、階段を上る方法の総数を求めるという問題です。E869120君は一歩で1段かL段上ることができ、彼が0段目からN段目に到達するまでの移動方法の総数を求めることが目的です。

この問題の解決策として、動的計画法(DP)という手法を使用します。

考えたことの内容

この問題の解決策として、N段目に到達するための方法は以下の2つから導かれます:

  • N-1段目にいて、そこから1段上がる
  • N-L段目にいて、そこからL段上がる

これは、N段目の状態(すなわち、移動方法の総数)を考えるには、N-1段目およびN-L段目までの状態(それぞれの移動方法の総数)を参照すれば良いということを意味します。

N段目を考えるためにN-1段目の情報が必要で、N-1段目を考えるにはN-2段目の情報を必要として・・・

詰まる所、0段目の状態から1段目,2段目・・・と順に通り数をカウントして、最終的にN段目の状態を求めればよいです。

実装した内容

このアプローチを実装するために、DPテーブルを作成します。このテーブルの各要素dp[i]は、i段目に到達するための移動方法の総数を表します。

典型解法:動的計画法

コード

# 入力の読み込み
N, L = map(int, input().split())

# NがLより小さい場合、移動方法は1通りしかないので、1を出力してプログラムを終了
if N < L:
    print(1)
    exit()

# DPテーブルの初期化
dp = [0 for i in range(N+1)]

# 0からL-1までの各段については、移動方法は1通りしかない
for i in range(L):
    dp[i] = 1

# L段目については、0段目から一気にL段上る方法と、1段ずつ上る方法の2通りがある
dp[L] = 2

# L+1段目からN段目までの各段については、直前の段から1段上る方法と、L段前から一気にL段上る方法の和が移動方法の総数となる
for i in range(L+1, N+1):
    dp[i] = dp[i-1] + dp[i-L]
    # 答えが大きくなりすぎるのを防ぐため、各段ごとに10^9 + 7で割った余りを求める
    dp[i] %= 10**9+7

# N段目に至る移動方法の総数を出力
print(dp[-1])

まとめ

前の問題【048 – I will not drop out(★3)】
次の問題【051 – Typical Shop(★5)】

コメント

タイトルとURLをコピーしました