#include <iostream>
#include <vector>
using namespace std;
int maxProfit(const vector<int>& prices)
{
int res = 0;
int n = prices.size();
if(n <= 0)
return 0;
vector<vector<int>>dp(n,vector<int>(2));
dp[0][0] = 0;
dp[0][1] = -prices[0];
for(int i = 1; i < n; ++i)
{
dp[i][1] = max(dp[i-1][1],-prices[i]);
dp[i][0] = max(dp[i-1][0],dp[i-1][1]+ prices[i]);
}
return dp[n-1][0];
}
int maxProfit_greedy(const vector<int>& prices)
{
if(prices.empty())return 0;
int n = prices.size();
int minVal = INT_MAX,profit = 0;
for(int price:prices)
{
minVal = min(minVal,price);
if(price > minVal)profit = max(profit,price-minVal);
}
return profit;
}
int maxProfit_II(const vector<int>& prices)
{
if(prices.empty())return 0;
int n = prices.size();
vector<vector<int>>dp(n,vector<int>(2));
dp[0][0] = 0;
dp[0][1] = -prices[0];
for(int i = 1; i < n; ++i)
{
dp[i][1] = max(dp[i-1][1],dp[i-1][0] - prices[i]);
dp[i][0] = max(dp[i-1][0],dp[i-1][1] + prices[i]);
}
return dp[n-1][0];
}
int maxProfit_II_greedy(const vector<int>& prices)
{
if(prices.empty())return 0;
int n = prices.size();
int profit = 0;
for(int i = 1; i < n; ++i)
{
if(prices[i-1] < prices[i])
{
profit += (prices[i] - prices[i-1]);
}
}
return profit;
}
int maxprofit(const vector<int>& prices,int fee)
{
if(prices.empty())return 0;
int n = prices.size();
vector<vector<int>>dp(n,vector<int>(2));
dp[0][0] = 0;
dp[0][1] = -prices[0];
for(int i = 1; i < n; ++i)
{
dp[i][0] = max(dp[i-1][0],dp[i-1][1]+prices[i]-fee);
dp[i][1] = max(dp[i-1][0] - prices[i],dp[i-1][1]);
}
return dp[n-1][0];
}
int maxProfit(const vector<int>& prices,int fee)
{
if(prices.empty())return 0;
int cash = 0, hold = -prices[0];
int n = prices.size();
for(int i = 1; i < n; ++i)
{
cash = max(cash,hold + prices[i]-fee);
hold = max(hold,cash - prices[i]);
}
return cash;
}
int maxProfit_cold(vector<int>prices)
{
if(prices.empty())return 0;
int n = prices.size();
if(n < 2)return 0;
vector<vector<int>>dp(n,vector<int>(2));
dp[0][0] = 0;
dp[0][1] = -prices[0];
dp[1][0] = max(dp[0][0],dp[0][1] + prices[1]);
dp[1][1] = max(dp[0][1],dp[0][0] - prices[1]);
for(int i = 2; i < n; ++i)
{
dp[i][1] = max(dp[i-1][1],dp[i-2][0]-prices[i]);
dp[i][0] = max(dp[i-1][0],dp[i-1][1]+prices[i]);
}
return dp[n-1][0];
}
int maxProfit123(const vector<int>& prices)
{
if(prices.empty())return 0;
int n = prices.size();
vector<vector<vector<int>>>dp(n,vector<vector<int>>(3,vector<int>(2)));
dp[0][1][0] = 0;
dp[0][1][1] = -prices[0];
dp[0][2][0] = 0;
dp[0][2][1] = -prices[0];
for(int i = 1; i < n; ++i)
{
for(int k = 2; k >= 1; --k)
{
dp[i][k][0] = max(dp[i-1][k][0],dp[i-1][k][1]+prices[i]);
dp[i][k][1] = max(dp[i-1][k][1],dp[i-1][k-1][0] - prices[i]);
}
}
return dp[n-1][2][0];
}
int maxProfit_K(const vector<int>&prices,int K)
{
if(prices.empty())return 0;
int n = prices.size();
vector<vector<vector<int>>>dp(n,vector<vector<int>>(K+1,vector<int>(2)));
for(int i = 0; i < n;++i)
{
for(int k = K; k >= 1; --k)
{
if(i == 0)
{
dp[0][k][0] = 0;
dp[0][k][1] = -prices[0];
continue;
}
dp[i][k][0] = max(dp[i-1][k][0],dp[i-1][k][1]+prices[i]);
dp[i][k][1] = max(dp[i-1][k][1],dp[i-1][k-1][0]-prices[i]);
}
}
return dp[n-1][K][0];
}
int main()
{
//LeetCode121
// vector<int>prices{7,1,5,3,6,4};
// vector<int>prices{7,6,4,3,1};
// cout << maxProfit(prices) << endl;
// cout << maxProfit_greedy(prices) << endl;
//LeetCode122
// vector<int>prices{1,2,3,4,5};
// vector<int>prices{7,1,5,3,6,4};
// cout << maxProfit_II(prices) <<endl;
// cout << maxProfit_II_greedy(prices) << endl;
// //LeetCode714
// vector<int>prices{1,3,2,8,4,9};
// int fee = 2;
// cout << maxprofit(prices,fee) << endl;
// cout << maxProfit(prices,fee) << endl;
//LeetCode309
// vector<int>prices{1,2,3,0,2};
// prices = {1};
// cout << maxProfit_cold(prices) << endl;
//LeetCode123
// vector<int>prices{3,3,5,0,0,3,1,4};
// cout << maxProfit_cold(prices) << endl;
//LeetCode188
int k = 2;
vector<int>prices{3,2,6,5,0,3};
cout << maxProfit_K(prices,k) << endl;
return 0;
}