動的計画法のアイデアの理解

動的計画法のアイデアの理解

I.概要

動的計画法の中核は動的遷移方程式です。この動的遷移方程式の意味は、現在の状態が前の状態に関連していることです。つまり、現在の状態が前の状態に関連している、または現在の状態が以前の状態に応じて「転送」されます。

ここでのもう1つの問題は、状態を定義する方法です。一般的に、この状態は他の多くの状態に関連しています。非常に抽象的なように聞こえますが、いくつかの例を見てみましょう

2.問題を通じて共通点を見つける

01ナップサック問題-問題につながる

この種の問題は、誰もがこの種の問題に精通していると思いますが、この記事の焦点は、問題を解決することではなく、動的計画法の特徴と、いくつかの動的計画法を通じて将来の動的計画法を行う方法を説明することです。プログラミングは質問をします。

まず、動的計画問題のdp配列がどのように定義されているかを見てみましょう。

画像の説明を追加してください

dp[i][j] = max(dp[i-1][j] + dp[i-1][j-weight])	// 意思就是在第i个物品选和不选两种情况里选一个最大值

i図の2次元配列から、バックパックの数やj容量がわかります。

多くの人は、他の人の解決策を読むと、他の人の問題解決のアイデアを理解でき、なぜこのように書かれているのかを理解できます。でも、こういう話題を自分で書いていると、とても違和感があり、生死が思い浮かびません。一番難しいのは、dp[i][j]真ん中の意味ij意味です。

私はここで私の個人的な意見を述べます:

	仔细观察图片中的行和列,就会发现他们都是一维的,例如【背包容量】是[0,maxWeight],【物品数量】是[0,maxNum],而在这个问题中【价值】是二维的,它受到物品数量和背包容量两个因素的影响。
	通常来说,动态规划的问题中对于每一步,都需要面临类似于【选与不选/向左还是向下】这种【二选一】,并且我们想要求得的值一般都会受到两个因素的影响,其中任何一个因素发生改变,都可能会让这个结果也发生改变。因此,通常来说,dp[i][j]的值就是我们【想要求得的结果】,而行和列则是影响着这个结果的两个维度,通常是一维的,也可以理解为是有一个确定范围的维度。
	而为什么物品的种类和价值我们不作为状态来考虑呢?因为他们是不变的,某一个物品的重量和价值已经是固定的了,不会去影响其别的属性。所以我在图中也吧这两个属性单独画在一起
	
	总结一下:动态规划题目特征【二选一】(两种情况选一种),定义行和列,通常是一维的属性,如【数量】,对于dp[i][j]数组中的值

LeetCode494.目標と-確認

トピック:

给你一个整数数组 nums 和一个整数 target 。

向数组中的每个整数前添加 '+' 或 '-' ,然后串联起所有整数,可以构造一个 表达式 :

例如,nums = [2, 1] ,可以在 2 之前添加 '+' ,在 1 之前添加 '-' ,然后串联起来得到表达式 "+2-1" 。
返回可以通过上述方法构造的、运算结果等于 target 的不同 表达式 的数目。

例:

示例 1:

输入:nums = [1,1,1,1,1], target = 3
输出:5
解释:一共有 5 种方法让最终目标和为 3 。
-1 + 1 + 1 + 1 + 1 = 3
+1 - 1 + 1 + 1 + 1 = 3
+1 + 1 - 1 + 1 + 1 = 3
+1 + 1 + 1 - 1 + 1 = 3
+1 + 1 + 1 + 1 - 1 = 3


示例 2:

输入:nums = [1], target = 1
输出:1

答え:

以前の推測によると、この質問を使用して、前のアイデアが正しいかどうかを確認します

なぜこれが動的計画法の問題だと言うのですか?タイトルから、[2つのうちの1つを選択]という数字が正または負のどちらかであることがはっきりとわかります。これは、前に述べた特性と非常に一致しています。

次のステップは、[望ましい結果]が何であるかを判断することです。明らかに、タイトルに出力したいのは[メソッドの数]です。次に、これによって影響を受ける2つの[メソッドの数]を分析します。 [メソッドの数]。次元係数の影響]、最初の1つは[数i]、範囲は[0,nums.length]、2番目は[最初のiの数の合計]、範囲は[-sum,+sum]

ここで、これが前に述べたことと一致しているかどうかを確認します。[望ましい結果]は2つの[1次元の要因]の影響を受けます。オプション番号の数が変わると、メソッドの数も変わります。[前のi番号の合計]が変わると、メソッドの数も変わることは間違いありません。確認後、問題ありません。

最後のステップは、動的伝達方程式の導出です。以前の基盤では、それを推測するだけで済みます。派生プロセスで問題が見つかった場合は、前の手順に戻って問題を見つけます。一次元因子が適切に選択されていない可能性があります。ここで、動的伝達方程式の導出を開始します。

img

上图是leetCode某题解的一个图,为了方便理解动态转移方程,我就拿过用了。

因为对于一个数,要么为正,要么为负

我们在进选择之前肯定是有一个起点的,这个起点就是可以选择的数是0个的时候,这个时候的总和为0,对应到数组中就是dp[0][8] = 1,表示0个数的时候,和为0,只有一种方法。

接下来我们遇到了第一个数:1,我们可以选择正的或者负的,就可以根据dp[0][8] = 1得到dp[1][7] = dp[1][7] + 1和dp[1][9] = dp[1][9] + 1;由此往下以此类推就会得到所有可能的情况,这里一定要自己去推敲一下。

由此,我们得到了【动态转移方程】: 逐层往下,一直dp[i][j]可以推导出dp[i+1][j+num[i]] = dp[i+1][j+num[i]] + dp[i][j],dp[i+1][j-num[i]] = dp[i+1][j-num[i]] + dp[i][j](这里的num[i]就是下一行要进行选择的数)

然后我们只【需要的结果】就是dp[nums.length][target + 8]

動的伝達方程式のその部分のコードのみがここに示されています。

for (int row = 0; row < nums.length; row++) {
    for (int col = 0; col < dp[row].length; col++) {
        if (dp[row][col]!=0){
            dp[ row + 1 ][ col - nums[row] ] += dp[row][col];
            dp[ row + 1 ][ col + nums[row] ] += dp[row][col];
        }
    }
}

別の考え方:

上記のアイデアは最も考えやすいものです。これよりも少し独創的なアイデアもありますが、考えるのは難しいでしょう。率直に言って、問題哪些是正哪些是负を別の問題に変えることです。 选哪些数组合成和为x、これは選択するかどうかの問題になりますが、すべての数値とターゲットターゲットの絶対値の合計(すべての正と負の数値の合計)である限り、これには少しの導出が必要ですが決定されると、それを取得できるので正数的和、それを解くだけで済み选前i个数组成和为x的方法个数ます。

質問の例1を例にとると、数値の合計が5の場合、ターゲットは3であり、正の数値を合計して4になる組み合わせの数を知る必要があるだけです。この理解はこれを言うために拡大しません

3.まとめ

今日は、主に動的計画問題の特徴、動的伝達方程式がどのように得られるか、そしてそのような問題に遭遇したときの解決策をどのように考えるかについて説明しました。将来的には、動的計画法の2次元配列を1ビット配列に最適化する方法について話す機会があります。

この記事の内容について疑問がある場合、または理解できない場合は、メッセージを残してください。メッセージが表示されたら、時間内に返信します。

おすすめ

転載: blog.csdn.net/weixin_44829930/article/details/120998682