ブルーブリッジカップエッセンシャルアルゴリズム3:動的計画法

アルゴリズムの原理

1.0アルゴリズムの紹介

動的計画法は、アルゴリズム設計に不慣れな初心者にとっても非常に困る問題であることは誰もが知っていると思います。理解しにくいこともありますが、実際に理解してみると、実際には動的計画法だと感じます。想像したほど難しくはありません。インターネット上には動的計画法の説明に関する記事もたくさんありますが、それらのほとんどは概念を説明し、原理を説明しているため、人々はあいまいで理解しにくいと感じます。アルゴリズムを理解する上で最も重要なことは練習だと思います。自分で練習することによってのみ、より速く上達することができます。動的計画法によって解決される最適化問題には、最適な部分構造と部分問題の重複という2つの要素が必要です。また、メモ化の方法についても説明し、メモ化のメカニズムを使用して、トップダウンの方法で重複するサブ問題を利用する方法について詳しく説明します。

2.0動的計画法で解決できる問題は何ですか?

動的計画法で解決できる問題には、一般に3つの特性があります。

  1. 最適化の原理:問題の最適解に含まれる部分問題の解も最適である場合、問題は最適な部分構造を持っている、つまり最適化の原理が満たされていると言われます。
  2. 後遺症なし:つまり、特定の段階の状態が決定されると、その後のこの状態の決定による影響を受けません。つまり、特定の状態の後のプロセスは前の状態に影響を与えず、現在の状態にのみ関連します。
  3. 重複するサブ問題があります。つまり、サブ問題は独立しておらず、意思決定の次の段階でサブ問題が複数回使用される可能性があります。(このプロパティは動的計画法のアプリケーションに必要な条件ではありませんが、このプロパティがないと、動的計画法アルゴリズムは他のアルゴリズムに勝る利点がありません)

3.0問題解決の手順

通常、動的計画法の問題は次の4つのステップで解決します。

  1. 最適なソリューションの構造的特徴である状態を定義します
  2. 状態再帰を実行して、再帰式を取得します
  3. 初期化する
  4. 結果を返す

古典的な例

ワシはひよこを食べる

トピックの説明

ここに画像の説明を挿入

ここに画像の説明を挿入

トピックのアイデアとコード

アイデア:ナップサック問題

#include<bits/stdc++.h>
using namespace std;
typedef long long int ll;
const ll maxn=1e5+10;
ll n;
ll a[maxn],b[maxn];
ll dp[100010];
ll sum=0;
int main(){
    
    
    scanf("%lld",&n);
    for(int i=1;i<=n;i++){
    
    
        scanf("%lld",&b[i]);
    }
    for(int i=1;i<=n;i++){
    
    
        scanf("%lld",&a[i]);
    }
    ll ma=0;
    for(int i=1;i<=n;i++){
    
    
        for(ll j=n;j>=b[i];j--){
    
    
            dp[j]=max(dp[j],dp[j-b[i]]+a[i]);
            ma=max(ma,dp[j]);

        }

    }
    printf("%lld",ma);
	return 0;
}


角かっこを削除します

リンク:元のタイトルリンク
ソース:Niuke.com

トピックの説明

给你一个合法的括号序列s1,每次你可以删除一个"()"
你可以删除0个或者多个"()"
求能否删成另一个括号序列s2

输入描述:
第一行输入一个字符串s (2|s|100)
第二行输入一个字符串t (2|t|100 )
输出描述:
如果可以输出"Possible"
否则输出"Impossible"

入力と出力のためにトピックリンクを開いてください!

トピックのアイデアとコード

アイデア: k =を使用して'('-delete')'の数を削除します。詳細については、コードを参照してください
。コード:

#include<bits/stdc++.h>
using namespace std;
typedef unsigned long long ll;
const ll N=105;
bool dp[N][N][N];
char str[N],str1[N];
int main()
{
    
    
 ios::sync_with_stdio(false);
 cin.tie(0);
 cout.tie(0);//对cin,cout的优化 
 cin>>str+1;
 cin>>str1+1;
 dp[0][0][0]=true;//边界初始化 
 for(int i=0;i<=strlen(str+1) ;i++)
 {
    
    
  for(int j=0;j<=strlen(str1+1) ;j++)
  {
    
    
   for(int k=0;k<=strlen(str+1)/2;k++)
   {
    
    
    if(dp[i][j][k])
    {
    
    
     if(!k&&str[i+1]==str1[j+1])dp[i+1][j+1][k]=true;//如果成立则前i+1中和j+1相匹配 
     if(str[i+1]=='(')dp[i+1][j][k+1]=true;//无论成立不,都要试试删除str[i+1] 
     else if(k)dp[i+1][j][k-1]=true; //如果有')',则有一对被删,k--; 
    }
   }
  }
 }
 if(dp[strlen(str+1)][strlen(str1+1)][0])cout<<"Possible"<<endl;//遍历到最后看看是否有成立的情况 
 else cout<<"Impossible"<<endl;
 return 0;
 }

その他のトピックについては、動的計画法のコラムをお読みください。

エピローグ


「未定の場合は春のそよ風に聞いてみてください。春のそよ風が話せない場合は心に従います」とは、何かに躊躇している場合は、春のそよ風にどうやってやるのか聞いてみてください。「未定の場合は春のそよ風を聞くことができます。春のそよ風が話せない場合は心に従います。」この文章はインターネット作家「風水オペラ王子」が書いた「建来」からのものです。原文は、「未定の場合は、春のそよ風を聞くことができます。あなたの心に従ってください」です。

ここに画像の説明を挿入


おすすめ

転載: blog.csdn.net/weixin_46627433/article/details/123647844