Technologieaustausch

[Sammlung falscher Fragen – Programmierfragen] Der beste Zeitpunkt zum Kauf und Verkauf von Aktien (4) (Dynamische Programmierung)

2024-07-12

한어Русский языкEnglishFrançaisIndonesianSanskrit日本語DeutschPortuguêsΕλληνικάespañolItalianoSuomalainenLatina

Link zur entsprechenden Frage:188. Der beste Zeitpunkt zum Kauf und Verkauf von Aktien IV – LeetCode

Niukes entsprechender Themenlink:Der beste Zeitpunkt zum Kauf und Verkauf von Aktien (4)_Niuke Topic_Niuke.com (nowcoder.com)


1. Analysieren Sie das Thema

1、Statusdarstellung

Zur besseren UnterscheidungkaufenUndverkaufen, wir ersetzen es durchVorräte habenUndkein BestandZwei Staaten.

  • f[i][j] bedeutet: NEIN. ich Am Ende des Tages ist es geschafft J Transaktion, derzeit inVorräte habenDer maximale Nutzen des Staates.
  • g[i][j] bedeutet: NEIN. ich Am Ende des Tages ist es geschafft J Transaktion, derzeit inkein BestandDer maximale Nutzen des Staates.

2. Zustandsübergangsgleichung

für F[ich][j], es gibt auch zwei Situationen, in denen die ich Wenn der Tag vorbei ist, ist alles fertig J Derzeit läuft eine TransaktionVorräte habenStatus:

  • existieren ich-1 Am Himmel, in den HändenVorräte haben, und gehandelt J Zweitklassig. Tun Sie am i-ten Tag nichts.Das Einkommen beträgt zu diesem Zeitpunkt f[ich - 1][j]
  • existieren ich-1 Am Himmel, in den Händenkeine Vorräte, und gehandelt J Zweitklassig.In der erstenich Als die Sonne unterging, kaufte ich Aktien Fahrkarte.Alsoich Letzten Endes gibt es Aktien.Das Einkommen beträgt zu diesem Zeitpunktg[i - 1][j] - Preise[i]

In den beiden oben genannten Fällen benötigen wir FolgendesMaximalwert, also lautet die Zustandsübergangsgleichung von f:

f[i][j] = max(f[i - 1][j], g[i - 1][j] - Preise[i]

für G[ich][j], wir haben die folgenden zwei Situationen, in denen wir können ich Wenn der Tag vorbei ist, ist alles fertig J Derzeit läuft eine Transaktionkeine VorräteStatus:

  • existieren ich-1 An dem Tag hatte ich keine Aktien in der Hand und habe sie gehandelt. J Zweitklassig.Tun Sie am i-ten Tag nichts .Das Einkommen beträgt zu diesem Zeitpunktg[ich - 1][j]
  • existieren ich-1 An dem Tag des Tages hatte ich Aktien in meinen Händen und handelte sie. j - 1 Zweitklassig.In der erstenich Wenn es sonnig ist, stellen Sie es auf Die Aktie wurde verkauft.Alsoich Am Ende des Tages handeln wir J Zweitklassig.Das Einkommen beträgt zu diesem Zeitpunkt f[ich - 1][j - 1] + Preise[i]

In den beiden oben genannten Fällen benötigen wir FolgendesMaximalwert,daher G Die Zustandsübergangsgleichung von lautet:

g[i][j] = max(g[i - 1][j], f[i - 1][j - 1] + Preise[i])

Die Handelsbeziehung zwischen ihnen ist wie folgt:


3. Initialisierung

Weil es nötig ist ich = 0 Der aktuelle Status, damit wir die erste Zeile initialisieren können.
  • wenn in der 0 Tage, kann nur in seinEinmal gekauftStaat, das Einkommen zu diesem Zeitpunkt ist -Preise[0] ,WeilDas f[0][0] = - Preise[0]
  • um zu nehmen max Wann, einige nicht existierende ZuständeKeine EinmischungFunktion, wir initialisieren sie alle als -INF(verwendenINT_MIN Während des Berechnungsprozesses wird dies der Fall seinÜberlaufDas Risiko hier INF Nimm die Hälfte 0x3f3f3f3f , klein genug).

4、Reihenfolge des Ausfüllens des Formulars

Füllen Sie jede Zeile von oben nach unten, jede Zeile von links nach rechts und beide Tabellen zusammen aus.

5、Rückgabewert

Gibt den Maximalwert im Verkaufszustand zurück, aber wir wissen nicht, wie oft er gehandelt wurde, also wird er zurückgegeben G Der Maximalwert in der letzten Zeile der Tabelle.


6、Optimierung

Unsere Anzahl an Transaktionen wird die Hälfte der gesamten Anzahl an Tagen nicht überschreiten, also können wir zunächst k Lassen Sie uns damit umgehen und die Größe des Problems optimieren:k = min(k, n / 2)


2. Code

  1. //力扣
  2. //【动态规划-二维dp-2个状态】
  3. class Solution {
  4. //f[i][j]:第i天结束后,完成了j次交易,此时处于“买入”状态下的最大利润
  5. //g[i][j]:第i天结束后,完成了j次交易,此时处于“卖出”状态下的最大利润
  6. private:
  7. const int INF=0x3f3f3f3f;
  8. public:
  9. int maxProfit(int k, vector<int>& prices) {
  10. int n=prices.size();
  11. k=min(k, n/2); //优化:处理最多交易次数
  12. vector<vector<int>> f(n, vector<int>(k+1, -INF));
  13. vector<vector<int>> g(n, vector<int>(k+1, -INF));
  14. f[0][0]=-prices[0], g[0][0]=0;
  15. for(int i=1; i<n; i++)
  16. {
  17. for(int j=0; j<=k; j++)
  18. {
  19. f[i][j]=max(f[i-1][j], g[i-1][j]-prices[i]);
  20. g[i][j]=g[i-1][j];
  21. if(j>=1) g[i][j]=max(g[i][j], f[i-1][j-1]+prices[i]);
  22. }
  23. }
  24. int res=0;
  25. for(int j=0; j<=k; j++)
  26. res=max(res, g[n-1][j]);
  27. return res;
  28. }
  29. };
  30. //【动态规划-二维dp-2k+1个状态】
  31. class Solution {
  32. //dp[i][0] -- 没有操作
  33. //下面j为奇数:买入;j为偶数:卖出 (j的范围:1~2k-1)
  34. //dp[i][j] -- 第1~k次买入
  35. //dp[i][j+1] -- 第1~k次卖出
  36. public:
  37. int maxProfit(int k, vector<int>& prices) {
  38. int n=prices.size();
  39. vector<vector<int>> dp(n, vector<int>(2*k+1));
  40. for(int j=1; j<2*k; j+=2)
  41. dp[0][j]=-prices[0];
  42. for(int i=1; i<n; i++)
  43. {
  44. for(int j=0; j<2*k; j+=2)
  45. {
  46. dp[i][j+1]=max(dp[i-1][j+1], dp[i-1][j]-prices[i]);
  47. dp[i][j+2]=max(dp[i-1][j+2], dp[i-1][j+1]+prices[i]);
  48. }
  49. }
  50. return dp[n-1][2*k];
  51. }
  52. };
  1. //牛客
  2. #include <iostream>
  3. #include <cstring>
  4. using namespace std;
  5. const int INF=0x3f3f3f3f;
  6. const int N=1010, M=110;
  7. int prices[N];
  8. int f[N][M], g[N][M];
  9. //f[i][j]:第i天结束后,完成了j次交易,此时处于“买入”状态下的最大利润
  10. //g[i][j]:第i天结束后,完成了j次交易,此时处于“卖出”状态下的最大利润
  11. int main()
  12. {
  13. int n, k;
  14. cin >> n >> k;
  15. for(int i=0; i<n; i++)
  16. cin >> prices[i];
  17. memset(f, -INF, sizeof(f));
  18. memset(g, -INF, sizeof(g));
  19. int res=0;
  20. f[0][0]=-prices[0], g[0][0]=0;
  21. for(int i=1; i<n; i++)
  22. {
  23. for(int j=0; j<=k; j++)
  24. {
  25. f[i][j]=max(f[i-1][j], g[i-1][j]-prices[i]);
  26. g[i][j]=g[i-1][j];
  27. if(j>0) g[i][j]=max(g[i][j], f[i-1][j-1]+prices[i]);
  28. res=max(res, g[i][j]);
  29. }
  30. }
  31. cout << res << endl;
  32. return 0;
  33. }
  34. //值得学习的代码
  35. #include <iostream>
  36. using namespace std;
  37. const int N = 1010, M = 110;
  38. int n, k, p[N];
  39. int f[N][M], g[N][M];
  40. int main()
  41. {
  42. cin >> n >> k;
  43. for(int i = 0; i < n; i++) cin >> p[i];
  44. k = min(k, n / 2);
  45. for(int j = 0; j <= k; j++) f[0][j] = g[0][j] = -0x3f3f3f3f;
  46. f[0][0] = -p[0], g[0][0] = 0;
  47. for(int i = 1; i < n; i++)
  48. {
  49. for(int j = 0; j <= k; j++)
  50. {
  51. f[i][j] = max(f[i - 1][j], g[i - 1][j] - p[i]);
  52. g[i][j] = g[i - 1][j];
  53. if(j >= 1) g[i][j] = max(g[i][j], f[i - 1][j - 1] + p[i]);
  54. }
  55. }
  56. int ret = 0;
  57. for(int j = 0; j <= k; j++) ret = max(ret, g[n - 1][j]);
  58. cout << ret << endl;
  59. return 0;
  60. }

3. Reflexion und Verbesserung

Eine Reihe von Fragen wie der Kauf und Verkauf von Aktien erfordern eine gründliche Vertrautheit mit den Kernwissenspunkten.