【AcWing 筆問題集】Blue Bridge Cup トピックス 突破口~動的プログラミング~dp入門(17)

目次

前に書かれています:

トピック: 821. ジャンプ階段 - AcWing 問題バンク

タイトル説明:

入力形式:

出力フォーマット:

データ範囲:

入力サンプル:

出力例:

問題解決のアイデア:

方法 1: 総当り検索

コード

方法 2: メモリ検索

コード

方法 3: 動的計画法

 コード

交流 !!!!!!!!!!

最後に書く:


前に書かれています:

どうすればアルゴリズムをうまく学習できますか?

個人的には質問の体系的なブラッシングが特に重要だと思いますが、

したがって、動的計画法をうまく学ぶためには、「DPカップ」に対処してください。

さっそくクイズを始めましょう!

トピック: 821. ジャンプ階段 - AcWing 問題バンク

タイトル説明:

階段には n 段あり、一度に 1 段または 2 段を歩くことができます。

0 番目のステップから n 番目のステップに移動する方法は何通りあるかを尋ねます。

入力形式:

整数 n を含む行。

出力フォーマット:

スキームの数を示す整数を含む合計 1 行。

データ範囲:

1≦n≦15

入力サンプル:

5

出力例:

8

問題解決のアイデア:

この質問は古典的な DP エントリの質問です。

レイヤーごとに進めて、再帰を一緒に開始する 3 つの方法を使用する予定です。

方法 1: 総当り検索

この質問は、以前の dfs ブラッシングの質問にもありましたが、

dfs を使用してすべてのスキームを検索できます。

三段跳びは、二段跳び+一段跳びの方法です。

四段跳びは、三段跳び+二段跳びの方法です。

等々: 

最後に答えを得ました:

コードは以下のように表示されます:

コード

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>

using namespace std;

int n = 0;

int dfs(int u)
{
    if(u == 1) return 1;
    else if(u == 2) return 2;
    
    return dfs(u - 1) + dfs(u - 2);
}

int main()
{
    scanf("%d", &n);
    int res = dfs(n);
    printf("%d", res);
    return 0;
}

方法 2: メモリ検索

実際、最初の方法の時間計算量は高すぎます。

これは 2 の n 乗の大きさです。

n >= 42 の場合、タイムアウトします。

 

時間を節約するために、メモ化された検索を使用できます。

計算した値を配列に記録し、

このように、検索値を繰り返し検索する必要はありません。

 コードの実装は次のとおりです。

コード

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>

using namespace std;

int n = 0;
int sum = 0;
const int N = 30;
int mem[N];//用一个数组记录

int dfs(int u)
{
    if(mem[u]) return mem[u];//如果记录过,就不用往下搜索了
    
    if(u == 1) return 1;
    else if(u == 2) return 2;
    else sum = dfs(u - 1) + dfs(u - 2);
    
    mem[u] = sum;//将该位置的值记录进数组
    return mem[u];
}

int main()
{
    scanf("%d", &n);
    int res = dfs(n);
    printf("%d", res);
    return 0;
}

この後、n = 100 の場合でも 1ms しかかからないことがわかりました。

方法 3: 動的計画法

実際、この問題の動的計画法は、

状態式は総当たり検索から導出され、

再帰検索は上から下へ検索することで、

下から上に逆戻りして、

実際、結果を取得するプロセスは、バックトラックするときです。

次に、このプロセスを検索する必要はなく、下から上に直接プッシュします。

これは動的計画法です。

コードの実装は次のとおりです。

 コード

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>

using namespace std;

int n = 0;
const int N = 30;
int fib[N];

int main()
{
    scanf("%d", &n);
    
    fib[1] = 1;
    fib[2] = 2;
    
    if(n == 1 || n == 2)
    {
        printf("%d", fib[n]);
        return 0;
    }
    
    for(int i = 3; i <= n; i++)
    {
        //这个就是动态规划的状态表达式
        fib[i] = fib[i - 1] + fib[i - 2];
    }
    printf("%d", fib[n]);

    return 0;
}

交流 !!!!!!!!!!

最後に書く:

以上がこの記事の内容です、お読みいただきありがとうございます。

この記事が気に入ったら、いいねとコメントをお願いします。また、ご意見をお書きください。

私と一緒にプログラミングを学びたい場合は、私に従ってください。私たちは一緒に学び、成長します。

今後もより質の高いコンテンツを出力していきますので、よろしくお願いします。

おすすめ

転載: blog.csdn.net/Locky136/article/details/129896223