#include <iostream>
#include <vector>
using namespace std;
#define INT_MIN -2147483647
class Solution {
public:
int maxProfit(vector<int> &prices, int times=2) {
// corner cases
if (prices.size() <= 1) return 0;
// define profit[i][k] at i day, at most k transactions
//
// the recursive equation is:
// profit[i][k] = max(profit[i-1][k], ->last trans@today
// max(prices[i]-prices[j]+profit[j][k-1]) ->last trans@day j)
// here j is at range [0, i-1]
// can also be rewritten as
// profit[i][k] = max(profit[i-1][k],
// prices[i]+max(profit[j][k-1]-prices[j]))
// if we write:
// S[l][k] = max(profit[j][k-1]-prices[j]), (j in [0, l)), then its equation is
// S[l][k] = max(profit[l-1][k-1]-prices[l-1], S[l-1][k]).
// Rewrite line 18 equation as equation set:
// S[i][k] = max(profit[i-1][k-1]-prices[i-1], S[i-1][k])
// profit[i][k] = max(profit[i-1][k], prices[i] + S[i][k])
//
int numOfDays = prices.size();
int totalTransTime = times;
// only need to construct one row
// at day 0, no matter how many trans its all 0 profit.
int* profit_i = new int[totalTransTime+1]();
int* S = new int[totalTransTime+1]();
for (int i = 0; i < totalTransTime + 1; i++)
S[i] = INT_MIN;
for (int i = 1; i < numOfDays; i++) {
for (int k = totalTransTime; k > 0; k--) {
int cand = profit_i[k - 1] - prices[i - 1];
if (cand > S[k]) {
S[k] = cand;
}
else
S[k] = S[k];
int term1 = profit_i[k];
int term2 = prices[i] + S[k];
profit_i[k] = term1 > term2 ? term1 : term2;
}
}
return profit_i[totalTransTime];
}
};
int main() {
vector<int> v{ 3, 3, 5, 0, 0, 3, 1, 4 };
int ret;
ret = (new Solution)->maxProfit(v);
cout << ret;
return 0;
}
I2luY2x1ZGUgPGlvc3RyZWFtPgojaW5jbHVkZSA8dmVjdG9yPgp1c2luZyBuYW1lc3BhY2Ugc3RkOwoKI2RlZmluZSBJTlRfTUlOIC0yMTQ3NDgzNjQ3IAoKY2xhc3MgU29sdXRpb24gewpwdWJsaWM6CglpbnQgbWF4UHJvZml0KHZlY3RvcjxpbnQ+ICZwcmljZXMsIGludCB0aW1lcz0yKSB7CgkJLy8gY29ybmVyIGNhc2VzCgkJaWYgKHByaWNlcy5zaXplKCkgPD0gMSkgcmV0dXJuIDA7CgoJCS8vIGRlZmluZSBwcm9maXRbaV1ba10gYXQgaSBkYXksIGF0IG1vc3QgayB0cmFuc2FjdGlvbnMKCQkvLyAKCQkvLyB0aGUgcmVjdXJzaXZlIGVxdWF0aW9uIGlzOgoJCS8vIHByb2ZpdFtpXVtrXSA9IG1heChwcm9maXRbaS0xXVtrXSwgLT5sYXN0IHRyYW5zQHRvZGF5CgkJLy8JCQkJCSAgbWF4KHByaWNlc1tpXS1wcmljZXNbal0rcHJvZml0W2pdW2stMV0pIC0+bGFzdCB0cmFuc0BkYXkgaikKCQkvLwkJCQkJICBoZXJlIGogaXMgYXQgcmFuZ2UgWzAsIGktMV0KCQkvLyBjYW4gYWxzbyBiZSByZXdyaXR0ZW4gYXMgCgkJLy8gcHJvZml0W2ldW2tdID0gbWF4KHByb2ZpdFtpLTFdW2tdLCAKCQkvLyAgICAgICAgICAgICAgICAgICAgcHJpY2VzW2ldK21heChwcm9maXRbal1bay0xXS1wcmljZXNbal0pKQoJCS8vIGlmIHdlIHdyaXRlOgoJCS8vIFNbbF1ba10gPSBtYXgocHJvZml0W2pdW2stMV0tcHJpY2VzW2pdKSwgKGogaW4gWzAsIGwpKSwgdGhlbiBpdHMgZXF1YXRpb24gaXMKCQkvLyBTW2xdW2tdID0gbWF4KHByb2ZpdFtsLTFdW2stMV0tcHJpY2VzW2wtMV0sIFNbbC0xXVtrXSkuCgkJLy8gUmV3cml0ZSBsaW5lIDE4IGVxdWF0aW9uIGFzIGVxdWF0aW9uIHNldDoKCQkvLyAgICAgU1tpXVtrXSA9IG1heChwcm9maXRbaS0xXVtrLTFdLXByaWNlc1tpLTFdLCBTW2ktMV1ba10pCgkJLy8gICAgIHByb2ZpdFtpXVtrXSA9IG1heChwcm9maXRbaS0xXVtrXSwgcHJpY2VzW2ldICsgU1tpXVtrXSkKCQkvLwoJCWludCBudW1PZkRheXMgPSBwcmljZXMuc2l6ZSgpOwoJCWludCB0b3RhbFRyYW5zVGltZSA9IHRpbWVzOwoJCS8vIG9ubHkgbmVlZCB0byBjb25zdHJ1Y3Qgb25lIHJvdwoJCS8vIGF0IGRheSAwLCBubyBtYXR0ZXIgaG93IG1hbnkgdHJhbnMgaXRzIGFsbCAwIHByb2ZpdC4KCQlpbnQqIHByb2ZpdF9pID0gbmV3IGludFt0b3RhbFRyYW5zVGltZSsxXSgpOwoJCWludCogUyA9IG5ldyBpbnRbdG90YWxUcmFuc1RpbWUrMV0oKTsKCQlmb3IgKGludCBpID0gMDsgaSA8IHRvdGFsVHJhbnNUaW1lICsgMTsgaSsrKQoJCQlTW2ldID0gSU5UX01JTjsKCQlmb3IgKGludCBpID0gMTsgaSA8IG51bU9mRGF5czsgaSsrKSB7CgkJCWZvciAoaW50IGsgPSB0b3RhbFRyYW5zVGltZTsgayA+IDA7IGstLSkgewoJCQkJaW50IGNhbmQgPSBwcm9maXRfaVtrIC0gMV0gLSBwcmljZXNbaSAtIDFdOwoJCQkJaWYgKGNhbmQgPiBTW2tdKSB7CgkJCQkJU1trXSA9IGNhbmQ7CgkJCQl9CgkJCQllbHNlCgkJCQkJU1trXSA9IFNba107CgkJCQkKCQkJCWludCB0ZXJtMSA9IHByb2ZpdF9pW2tdOwoJCQkJaW50IHRlcm0yID0gcHJpY2VzW2ldICsgU1trXTsKCgkJCQlwcm9maXRfaVtrXSA9IHRlcm0xID4gdGVybTIgPyB0ZXJtMSA6IHRlcm0yOwoJCQl9CgkJfQoJCXJldHVybiBwcm9maXRfaVt0b3RhbFRyYW5zVGltZV07Cgl9Cn07CgppbnQgbWFpbigpIHsKCXZlY3RvcjxpbnQ+IHZ7IDMsIDMsIDUsIDAsIDAsIDMsIDEsIDQgfTsKCWludCByZXQ7CglyZXQgPSAobmV3IFNvbHV0aW9uKS0+bWF4UHJvZml0KHYpOwoJY291dCA8PCByZXQ7CgoJcmV0dXJuIDA7Cn0=