目次
動的プログラミングを学ぶにはどうすればよいですか?
動的プログラミングの学習はもちろん、アルゴリズムの学習にも近道はありません。
動的プログラミング アルゴリズムに関する質問を私と一緒に解決し、動的プログラミングを一緒に学びましょう!
1. トピック分析
トピックリンク: 123. 株式の売買に最適な時期 III - LeetCode
株の売買というテーマは概ね同じですが、細部に若干の違いがある点が異なります。
たとえば、この質問では、完了できるトランザクションの最大数を 2 に制限しています。(在庫は1個のみです)
2. アルゴリズム原理
1. ステータス表現
dp[ i ] は i 日目までに得られる最大利益を表します。
実際、彼をさらに 2 つの状況に分けることができます。
購入ステータスと取引可能ステータス、および完了したトランザクションの数を記録する必要があります
f [ i ][ j ] は、i 日目の終了後、j 回のトランザクションが完了し、「買い」状態で最大の利益が得られたことを意味します。
g [ i ][ j ] は、i 日目の終了後に j 回の取引が完了し、「取引可能」状態での最大利益が得られることを意味します。
ここでも買い状態とは手持ち株のことを指しますが、
取引可能ステータスとは、手持ちの株式が存在しないことを意味します。
2. 状態遷移方程式
f [ i ][ j ] から分析してみましょう。2 つの状況があります。1 つは昨日購入し、もう 1 つは昨日取引可能です。
購入状態では何もできませんが、取引状態では、今日購入する限り、購入状態に入ることができます。つまり、次のようになります。
f [ i ][ j ] = max( f [ i - 1 ][ j ],g [ i - 1 ][ j ] - p [ i ] )
次に g [ i ][ j ]、同じ 2 つのケース、
購入状態の場合は売ります。その日の j は現在の j より 1 小さいです。取引可能な状態の場合は、何もしないでください。
g [ i ][ j ] = max( g[ i - 1 ][ j ],f [ i - 1 ][ j - 1 ] + p [ i ] )
3. 初期化
境界線を越えないようにするには、特別な処理をする必要がありますが、
次に、前の値が次の値に影響を与えないようにするには、配列の内容を負の無限大に初期化する必要があります。
次に、 f[ 0 ][ 0 ] = -p[ 0 ] と置き、 g[ 0 ][ 0 ] = 0 とします。
4.注文の実行
上から下、左から右の順に、2 つのフォームを一緒に記入します。
5. 戻り値
g テーブルの最後の行の最大値
3. コードの書き方
class Solution {
public:
int maxProfit(vector<int>& prices) {
int n = prices.size();
vector<vector<int>> f(n, vector<int>(3, -0x3f3f3f3f));
auto g = f;
f[0][0] = -prices[0], g[0][0] = 0;
for(int i = 1; i < n; i++) {
for(int j = 0; j < 3; j++) {
f[i][j] = max(f[i - 1][j], g[i - 1][j] - prices[i]);
g[i][j] = g[i - 1][j];
if(j > 0) g[i][j] = max(g[i][j], f[i - 1][j - 1] + prices[i]);
}
}
int ans = 0;
for(auto e : g[n - 1]) ans = max(ans, e);
return ans;
}
};
最後に次のように書きます。
以上が今回の記事の内容となります、読んでいただきありがとうございます。
何かを得たと感じたら、ブロガーに「いいね! 」を与えることができます。
記事の内容に抜けや間違いがある場合は、ブロガーにプライベートメッセージを送信するか、コメントエリアで指摘してください〜