質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
Ruby on Rails 5

Ruby on Rails 5は、オープンソースのWebアプリケーションフレームワークです。「同じことを繰り返さない」というRailsの基本理念のもと、他のフレームワークより少ないコードで簡単に開発できるよう設計されています。

Ruby

Rubyはプログラミング言語のひとつで、オープンソース、オブジェクト指向のプログラミング開発に対応しています。

Ruby on Rails 6

Ruby on Rails 6は、オープンソースのWebアプリケーションフレームワークです。「同じことを繰り返さない」というRailsの基本理念のもと、他のフレームワークより少ないコードで簡単に開発できるよう設計されています。

Ruby on Rails

Ruby on Railsは、オープンソースのWebアプリケーションフレームワークです。「同じことを繰り返さない」というRailsの基本理念のもと、他のフレームワークより少ないコードで簡単に開発できるよう設計されています。

Q&A

解決済

1回答

552閲覧

階段の登り方は何通りあるか問題 d[i] = dp[i] + dp[i-a]の式の意味

mingo09

総合スコア23

Ruby on Rails 5

Ruby on Rails 5は、オープンソースのWebアプリケーションフレームワークです。「同じことを繰り返さない」というRailsの基本理念のもと、他のフレームワークより少ないコードで簡単に開発できるよう設計されています。

Ruby

Rubyはプログラミング言語のひとつで、オープンソース、オブジェクト指向のプログラミング開発に対応しています。

Ruby on Rails 6

Ruby on Rails 6は、オープンソースのWebアプリケーションフレームワークです。「同じことを繰り返さない」というRailsの基本理念のもと、他のフレームワークより少ないコードで簡単に開発できるよう設計されています。

Ruby on Rails

Ruby on Railsは、オープンソースのWebアプリケーションフレームワークです。「同じことを繰り返さない」というRailsの基本理念のもと、他のフレームワークより少ないコードで簡単に開発できるよう設計されています。

0グッド

0クリップ

投稿2022/06/20 04:56

編集2022/06/20 14:37

【問題】
整数 n, a, b, c が与えられます。
階段を上るのに、1歩で a 段または b 段または c 段を上ることができるとき、n 段の階段を上る方法は何通りあるでしょうか。(Rubyのコードで解答してください。)

入力される値

n a b c

期待する出力

n 段の階段を上る方法の数を1行に出力してください。

条件
すべてのテストケースにおいて、以下の条件をみたします。

・ 1 ≦ n ≦ 30 ・ 1 ≦ a ≦ 7 ・ 1 ≦ b ≦ 7 ・ 1 ≦ c ≦ 7 ・ a ≠ b ・ b ≠ c ・ c ≠ a

入力例1

10 2 3 4

出力例1

17

【調べて書いたコード】

Ruby

1def solve(gets) 2 n, a, b, c = gets.split.map(&:to_i) 3 # dpテーブル初期化 4 # 0段目には上らなくても到達できる 5 dp = [1] + [0] * n 6 # dpテーブル更新 7 1.upto(n) do |i| 8 # i-a 段目から a 段上って i 段へ到達 9 dp[i] += dp[i - a] if i >= a 10 # i-b 段目から b 段上って i 段へ到達 11 dp[i] += dp[i - b] if i >= b 12 # i-c 段目から c 段上って i 段へ到達 13 dp[i] += dp[i - c] if i >= c 14 end 15 # n 段目に行く経路数を返す 16 dp[n] 17end 18puts solve(gets)

【質問したいこと】

dp[i] += dp[i - a] if i >= a

この行の式は次のようになるかと思います。

dp[i] = dp[i] + dp[i - a] if i >= a

両辺にdp[i]という項があることが非常に違和感があるのですが、この式はどのように解釈したらいいでしょうか。
dp[i]はi段目に行く経路だと認識しています。
i段目に行く経路にi-a段目に行く経路を足してi段目に行く経路になる理由がわかりません。ご教授いただけたら嬉しいです。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

ベストアンサー

aを1~7で場合分けし、その中で、bを場合分けし、またその中でcを場合分けする

残念ながら、そもそも問題文を正確に読めていません。
n, a, b, cはテストケースごとに固定されています。
たとえば入力例1は、a2で固定です。


とりあえず単純に考えると
「階段を上るのに、1歩で a 段または b 段または c 段を上ることができるとき、n 段の階段を上る方法」の数を
長ったらしいのでstep(n,a,b,c)と呼ぶことにすると

  • n = 0のとき 1通り
  • n < 0 のとき 0通り
  • それ以外のとき、 step(n-a,a,b,c) + step(n-b,a,b,c) + step(n-c,a,b,c)通り

です。


問題文でググると動的計画法の典型問題らしいので、動的計画法で解くのでしょう。

k=0, 1, 2, 3, 4, ..., nとして、
「階段を上るのに、1歩で a 段または b 段または c 段を上ることができるとき、k 段の階段を上る方法」の数をdp[k]とすると
dp[k] = dp[k-a] + dp[k-b] + dp[k-c] (インデックスが負になる場合を適宜考慮する)
dp[0] = 1
という関係になりますので
k=0から計算していけばよいです。


両辺にdp[i]という項があることが非常に違和感があるのですが、この式はどのように解釈したらいいでしょうか。

これなら分かりますか?

ruby

1 sum = 0 2 sum += dp[i - a] if i >= a 3 # i-b 段目から b 段上って i 段へ到達 4 sum += dp[i - b] if i >= b 5 # i-c 段目から c 段上って i 段へ到達 6 sum += dp[i - c] if i >= c 7 8 dp[i] = sum

やっていることはこれと全く一緒です。

投稿2022/06/20 05:15

編集2022/06/20 23:32
ozwk

総合スコア13521

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

mingo09

2022/06/20 05:22 編集

コメントありがとうございます。 たしかにそうですね。nをaやb,cで割った商で場合わけになりますね。 ただ、それでも力技でやる方法しか思い浮かばないです。
ozwk

2022/06/20 05:26

追記しました
ozwk

2022/06/20 07:04

> nをaやb,cで割った商で場合わけになりますね。 ちなみに商でどう場合分けるのでしょうか?
mingo09

2022/06/20 13:45

nをaで割った商から-1ずつしていって場合分けする感じに思っています。
mingo09

2022/06/21 02:48

ご回答ありがとうございます。 そのような感じだろうとは思ったのですが、dp[i]に意味が生じるとよくわからなくなっている状態です。 dp[i] = dp[i] + dp[i-a] の式を日本語にするとイメージができなくなっています。
ozwk

2022/06/21 02:55 編集

* dp[i]を計算する直前の時点ではdp[i]の値は0である。 * dp[i]の計算にdp[i]は必要がない。 というわけで、回答で言う変数sumの代わりにdp[i]を使っているだけです。 プログラミング的な操作と数学的な意味を混ぜないように気をつけてください。 別な言い方をすれば dp[i]にdp[i-a]とdp[i-b]とdp[i-c]をどんどん足しているだけです。
mingo09

2022/06/21 03:12 編集

1.upto(n) do |i| # i-a 段目から a 段上って i 段へ到達 puts dp[i] dp[i] += dp[i - a] if i >= a puts dp[i] # i-b 段目から b 段上って i 段へ到達 dp[i] += dp[i - b] if i >= b # i-c 段目から c 段上って i 段へ到達 dp[i] += dp[i - c] if i >= c end 上のように、前後でdp[i]の内容を確認してみたところ、はじめのdp[i]は常に0になっていました。 なんとなくわかったようなきがします。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問