Advertisement
Fastrail08

Best Time to Buy & Sell Stocks with Transaction Fee

Jun 18th, 2025
297
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 14.54 KB | None | 0 0
  1. #include <bits/stdc++.h>
  2. using namespace std;
  3.  
  4. void getMaxProfitInfiniteTransactionWithFee(int level, int transactionOpen, int profit, int &maxProfit, vector<int> &prices, int fee){
  5.    
  6.     if(level >= prices.size()){
  7.         maxProfit = max(maxProfit, profit);
  8.         return;
  9.     }
  10.     //levels - each stock price
  11.     //options - buy, sell or don't do anything
  12.    
  13.     // transaction opened / buying
  14.     if(!transactionOpen){
  15.         getMaxProfitInfiniteTransactionWithFee(level + 1, 1, profit - prices[level], maxProfit, prices, fee);
  16.     }
  17.    
  18.     //transaction closed / selling
  19.     if(transactionOpen){
  20.         getMaxProfitInfiniteTransactionWithFee(level + 1, 0, profit + prices[level] - fee, maxProfit, prices, fee);
  21.     }
  22.    
  23.     //Don't do anything / neither buy nor sell
  24.     getMaxProfitInfiniteTransactionWithFee(level + 1, transactionOpen, profit, maxProfit, prices, fee);
  25.    
  26. }
  27.  
  28. int getMaxProfitInfiniteTransactionWithFeeMemo(int level, int transactionOpen, vector<int> &prices, int fee, vector<vector<int> > &memo){
  29.    
  30.     if(level >= prices.size()){
  31.         return 0;
  32.     }
  33.    
  34.     if(memo[level][transactionOpen] != -1){
  35.         return memo[level][transactionOpen];
  36.     }
  37.    
  38.     //levels - each stock price
  39.     //options - either buy, sell or don't do anything
  40.    
  41.     int bought = 0, sold = 0, na = 0;
  42.    
  43.     //buy only if no transaction opened
  44.     if(!transactionOpen){
  45.         bought += getMaxProfitInfiniteTransactionWithFeeMemo(level + 1, 1, prices, fee, memo) - prices[level];
  46.     }
  47.    
  48.     //sell only if a transaction is open
  49.     if(transactionOpen){
  50.         sold += getMaxProfitInfiniteTransactionWithFeeMemo(level + 1, 0, prices, fee, memo) + prices[level] - fee;
  51.     }
  52.    
  53.     // don't do anything
  54.     na = getMaxProfitInfiniteTransactionWithFeeMemo(level + 1, transactionOpen, prices, fee, memo);
  55.    
  56.     return memo[level][transactionOpen] = max(na, max(bought, sold));
  57.    
  58. }
  59.  
  60.  
  61. int getMaxProfitInfiniteTransactionWithFeeDP(vector<int> &prices){
  62.     /*
  63.     Storage & Meaning - dp[i][0] = processing/decision made upto ith level where the transaction ends as closed
  64.                         dp[i][1] = processing/decision made upto ith level where the transaction ends as open
  65.                        
  66.                         dp[i][0] = decision made upto (i - 1)th level and the ith level ends with 0/sell state
  67.                         dp[i][1] = decision made upto (i - 1)the level and the ith level ends with 1/buy state
  68.     */
  69.    
  70.     /*
  71.     Direction -
  72.    
  73.         Identify where the smaller subproblems and larger subproblems lie. To do this see what is the base case.
  74.         In string DP you can do it from either side, but it is convenient to start from 0th index, as definition will make more sense then.
  75.        
  76.         When you start from left OR from 0th level, generally the subproblems are defined as 'upto ith index ending with char/item/0' and when you start from right OR from (N - 1)th level, subproblems are defined as 'starting from ith index with starting char/item/0'
  77.        
  78.         You will already have answers to smaller subproblems, now you need to explore all the options at previous level for the current level, to see where the arrows will land at.
  79.        
  80.         You need to be able to fill all the cells corresponding to the current level.
  81.         FOR 1D dp dp[i]... you need to be able to fill the cell dp[i]
  82.        
  83.         FOR 2D dp dp[i][j]... you need to be able to fill the cell dp[i][0] upto dp[i][j]
  84.        
  85.         Simply go to just previous states, define them what they, explore the options, [as you explored the options at a level {(i - 1), or some dp[i - 1][j], you will simply move to the next level{(i), dp[i][?], you just need to figure out what dp cell it will fall in at the next level, figure out the ?]. You can figure it out by attaching the option to the meaning of (i - 1) and see what new meaning it has.
  86.        
  87.         For eg -
  88.         consider question AiBjCk
  89.         dp[i][a] = Stores all the VALID subsequences ENDING with a, when the DECISION is made upto level i.
  90.         dp[i][b] = Stores all the VALID subsequences ENDING with b, when the DECISION is made upto level i.
  91.         dp[i][c] = Stores all the VALID subsequences ENDING with c, when the DECISION is made upto level i.
  92.        
  93.        
  94.         we need to be able to fill any ith level COMPLETELY, EVERY CELL defined at ith level. So the level variable here is i. So we need to be able to fill dp[i][a], dp[i][b], dp[i][c]
  95.        
  96.         To do this go the past level, here (i - 1)[it can be i - 1, or i - 2, just see the recursion code, what are jumps made to the next level (if there is level + 1, level + 2, ..you need to see what all paths from every past level, if we explore the options for arr[i], string[i], item[i])]
  97.        
  98.         In the above question AiBjCk, we are jumping atmost level + 1 in any call, so we just need to explore only the (i - 1)th level, if we are to find answers for ith level.
  99.        
  100.        
  101.         dp[i - 1][a] = all the valid subsequences ending with a, when decision is made upto (i - 1)th level.
  102.         And similarly for dp[i - 1][b] and dp[i - 1][c]. As you are doing DP, you would already have this table filled up for these cells.
  103.        
  104.         What you have to do now is to explore the options which are available at ith level, and explore it here.
  105.        
  106.         for eg - imagine the string was abcbabc, and current ith level is at index 3, that is string[i] = 'b'.
  107.        
  108.         AAYEGA YA NAHI AAYEGA (simple choice for a subsequence)
  109.         The options available at each level is to -
  110.         include the character or exclude the character
  111.         OR
  112.         Select the character or don't select the character
  113.         OR
  114.         Either character part of subsequence or not the part of subsequence
  115.        
  116.         So for filling up dp[i][b], explore the option 'b' at the previous level so that you can land on the current level.
  117.        
  118.         dp[i][a] stores the answer AFTER it has processed the ith level/char, and you land up on ith level only when you would have explored it at previous state.
  119.        
  120.         So if ith char is 'b', we would be the option available at the previous level (i - 1) is to either include or exclude b
  121.        
  122.        
  123.        
  124.                           dp[i][a]      (exclude b)
  125.                         -
  126.                       -
  127.                     -
  128.         dp[i - 1][a]
  129.                     -
  130.                       -
  131.                         -
  132.                           dp[i][b]      (include b)
  133.        
  134.        
  135.         So doing this for all past states, we get
  136.        
  137.                             dp[i][b]      (exclude b)
  138.                         -
  139.                       -
  140.                     -
  141.         dp[i - 1][b]
  142.                     -
  143.                       -
  144.                         -
  145.                           dp[i][b]        (include b)
  146.        
  147.        
  148.        
  149.                             dp[i][c]      (exclude b)
  150.                         -
  151.                       -
  152.                     -
  153.         dp[i - 1][c]
  154.                     -
  155.                       -
  156.                         -
  157.                           [INVALID CASE]  (include b)
  158.                          
  159.                          
  160.         [INVALID CASE] as - dp[i - 1][c] contains all the subsequences that ends with 'c'. Now you explored the option to include 'b', which means 'b' will be added at the end of the subsequences making all the subsequences end with 'b',  that was already ending with 'c' at the previous level, which will make subsequences of type aabcb, abcb, aabbbccb, which are all invalid cases.
  161.        
  162.         During Recursion we managed to avoid this invalid call by adding a condition s[lastChar] <= s[level], so that if the last char was a, we can call to a,b or c depending on what char lies at current level.
  163.         If last char was b, we can only call to b & c, and if last char was c, we can only call to c to only have valid subsequences at every level.
  164.        
  165.         If current character s[i] = 'b', the answer will be filled in dp[i][b], and to form the answer dp[i][b]
  166.         Option available at the previous level, either to include b or exclude b.
  167.         We see what all paths lead to dp[i][b], from all previous levels dp[i - 1][a], dp[i - 1][b], dp[i - 1][c].
  168.        
  169.         According to the diagram, 1 path from dp[i - 1][a] (option - if b included, now string will end with b)
  170.                                   2 paths from dp[i - 1][b] (both option available, as string will end with b only)
  171.                                   0 paths from dp[i - 1][c] (1 option leads to dp[i][c], other is invalid)
  172.                                  
  173.                                  
  174.                                  
  175.         [INVALID case] =
  176.         dp[i- 1][c] = agar (i - 1)th level/index padi hui saari subsequences jo 'c' se end hoti hai agar uske aage mai 'b' laga du(include b), to mujhe vo saari subsequences milengi ith level/index pe jo 'b' se end hogi. But 'b' se pehle vo 'c' pe end ho rahi thi, to 'b', 'c' ke baad aaya jiske kaaran subsquence invalid ho jaayega according to question.
  177.                                  
  178.                                  
  179.        
  180.         We will compute this for every possible character -
  181.        
  182.         IF s[i] = a, then we will fill dp[i][a], options at previous level = either include 'a' or exclude 'a'
  183.        
  184.                             dp[i][a]      (exclude a)
  185.                         -
  186.                       -
  187.                     -
  188.         dp[i - 1][a]
  189.                     -
  190.                       -
  191.                         -
  192.                             dp[i][a]      (include a)
  193.                            
  194.                            
  195.                            
  196.                             dp[i][b]      (exclude a)
  197.                         -
  198.                       -
  199.                     -
  200.         dp[i - 1][b]
  201.                     -
  202.                       -
  203.                         -
  204.                             [INVALID case]  (include a)
  205.                            
  206.                            
  207.        
  208.                             dp[i][c]       (exclude a)
  209.                         -
  210.                       -
  211.                     -
  212.         dp[i - 1][c]
  213.                     -
  214.                       -
  215.                         -
  216.                             [INVALID case]      (include a)
  217.                            
  218.          
  219.          
  220.         dp[i][a] = dp[i - 1][a] + dp[i - 1][a] + 1  (1 would be there as subsquence a is allowed)
  221.         dp[i - 1][a] = If we don't select the current char 'a' at level i, still the subsequences will be ending with a
  222.          
  223.         dp[i - 1][a] = If we select current char 'a', the subsequences will end with a.
  224.        
  225.         1 = the current character itself is a valid subsequence.
  226.        
  227.         dp[i][a] =
  228.         dp[i - 1][a] = i - 1 level tak ka decision lene ke baad vo saari subsequences jo 'a' se end hoti hai, uske aage mai current level(ith level) waala 'a' na lagaon, tab bhi mujhe 'a' se end hone waali subsequences milengi, after making decisions upto ith level which is nothing but dp[i][a].
  229.        
  230.         dp[i - 1][a] = i - 1 level tak ka decision lene ke baad vo saari subsequences padi hai yaha pe jo 'a' se end hoti hai, uske aage mai agar current level waala 'a' laga du, ith level ka decision lene tak /process karne ke baad, mujhe 'a' se end hone waali subsequences milengi.
  231.                            
  232.         1 = vo current level waala 'a' khud ek valid subsequence hai
  233.        
  234.        
  235.        
  236.        
  237.        
  238.                            
  239.         IF s[i] = 'c' then we will fill dp[i][c], options at previous level = either include 'c' or exclude 'c'
  240.        
  241.                
  242.                             dp[i][a]      (exclude c)
  243.                         -
  244.                       -
  245.                     -
  246.         dp[i - 1][a]
  247.                     -
  248.                       -
  249.                         -
  250.                             [INVALID CASE]      (include c)
  251.                                    
  252.                                    
  253.                
  254.                             dp[i][b]      (exclude c)
  255.                         -
  256.                       -
  257.                     -
  258.         dp[i - 1][b]
  259.                     -
  260.                       -
  261.                         -
  262.                             dp[i][c]      (include c)
  263.        
  264.        
  265.                
  266.                             dp[i][c]      (exclude c)
  267.                         -
  268.                       -
  269.                     -
  270.         dp[i - 1][c]
  271.                     -
  272.                       -
  273.                         -
  274.                             dp[i][c]      (include c)
  275.                            
  276.        
  277.        
  278.         so dp[i][c] = dp[i - 1][c] + dp[i - 1][c] + dp[i - 1][b]
  279.        
  280.        
  281.         dp[i - 1][c] = agar i - 1th level pe 'c' se end hone waali subsequences ke aage agar mai current level waala 'c' na lagaon to merko 'c' se end hone waali subsequences milengi ith level par
  282.         dp[i - 1][c] = agar i - 1th level pe 'c' se end hone waali subsequences ke aage agar mai current level waala 'c' laga du to to 'c' se end hone waali subsequences hi milengi ith level par
  283.         dp[i - 1][b] = agar i - 1th level pe 'b' se end hone waali saari subsequences ke aage mai 'c' laga du, to mujhe vo saari subsequences mil jaayengi jo 'c' se end hogi ith level par.
  284.        
  285.        
  286.         For any dp[i][j], identify what all smaller states could have made the answer for the current state,
  287.         analyse all the valid options at previous level(here, i - 1) and when you explore an option [that is when
  288.         you make a recursive call from a level to the next level]
  289.        
  290.         In recursion when you are on a level, you analyse what all VALID options are(sudoku, binary strings)
  291.         and then you try to explore each option by making a recursive call, which takes you to the next level.
  292.        
  293.        
  294.     */
  295. }
  296.  
  297. int main() {
  298.     // your code goes here
  299.     int n, fee;
  300.     cin >> n;
  301.     vector<int> prices(n);
  302.     for(int i = 0; i < n; i++){
  303.         cin >> prices[i];
  304.     }
  305.     cin >> fee;
  306.     /*
  307.     RECURSION CALL
  308.         int maxProfit = 0;
  309.         getMaxProfitInfiniteTransactionWithFee(0, 0, 0, maxProfit, prices, fee);
  310.         cout << maxProfit << '\n';
  311.     */
  312.    
  313.     /*
  314.     MEMO CALL
  315.        
  316.    
  317.     */
  318.     vector<vector<int> > memo(n, vector<int>(2, -1));
  319.     cout << getMaxProfitInfiniteTransactionWithFeeMemo(0, 0, prices, fee, memo) << '\n';
  320. }
  321.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement