一、按摩师(打家劫舍 | )
1.链接
面试题 17.16. 按摩师 - 力扣(LeetCode)
2.描述
3.思路
4.参考代码
class Solution {
public:
int massage(vector<int>& nums)
{
int n = nums.size();
if(n == 0)
{
return 0;
}
vector<int> f(n);
vector<int> g(n);
f[0] = nums[0];
g[0] = 0;
for(int i = 1;i<n;i++)
{
f[i] = nums[i] + g[i-1];
g[i] = max(f[i-1],g[i-1]);
}
return max(f[n-1],g[n-1]);
}
};
二、打家劫舍 ||
1.链接
213. 打家劫舍 II - 力扣(LeetCode)
2.描述
3.思路
4.参考代码
class Solution {
public:
int rob1(vector<int>& nums,int begin,int end)
{
if(begin > end)
{
return 0;
}
vector<int> f(nums.size());
vector<int> g(nums.size());
f[begin] = nums[begin];
g[begin] = 0;
for(int i = begin+1 ; i<=end ; i++)
{
f[i] = g[i-1] + nums[i];
g[i] = max(f[i-1],g[i-1]);
}
return max(f[end],g[end]);
}
int rob(vector<int>& nums)
{
int n = nums.size();
if(n == 0) return 0;
return max(nums[0]+rob1(nums,2,n-2),rob1(nums,1,n-1));
}
};
三、删除并获得点数
1.链接
740. 删除并获得点数 - 力扣(LeetCode)
2.描述
3.思路
题目分析,本题中的数据和数组的顺序本身并不相关,根据题意我们可以对数据进行一个预处理,用一个数组,利用数组的下标去和数据建立一个映射关系,这样就可以把问题转换成了打家劫舍问题,打家劫舍的思路就不重复了
4.参考代码
class Solution {
public:
int deleteAndEarn(vector<int>& nums)
{
//对数据预处理,先找到最大值
int n = nums[0];
for(int i = 1;i<nums.size();i++)
{
n = max(n,nums[i]);
}
vector<int> hash(n+1,0);
for(int i = 0;i<nums.size();i++)
{
hash[nums[i]]++;
}
auto f = hash;
auto g = hash;
f[1] = hash[1];
g[1] = 0;
for(int i = 2;i<=n;i++)
{
f[i] = g[i-1] + hash[i]*i;
g[i] = max(f[i-1],g[i-1]);
}
return max(f[n],g[n]);
}
};
四、粉刷房子
1.链接
LCR 091. 粉刷房子 - 力扣(LeetCode)
2.描述
3.思路
4.参考代码
class Solution {
public:
int minCost(vector<vector<int>>& costs)
{
int n = costs.size();
vector<int> f(n);
vector<int> g(n);
vector<int> h(n);
f[0] = costs[0][0] , g[0] = costs[0][1] , h[0] = costs[0][2];
for(int i = 1; i < n;i++)
{
f[i] = costs[i][0] + min(g[i-1],h[i-1]);
g[i] = costs[i][1] + min(f[i-1],h[i-1]);
h[i] = costs[i][2] + min(f[i-1],g[i-1]);
}
return min(min(f[n-1],g[n-1]),h[n-1]);
}
};
五、买卖股票的最佳时机含冷冻期
1.链接
309. 买卖股票的最佳时机含冷冻期 - 力扣(LeetCode)
2.描述
3.思路
4.参考代码
class Solution
{
public:
int maxProfit(vector<int>& prices)
{
int n = prices.size();
vector<vector<int>> dp(n,vector<int>(3,0));
//dp[i][0] 表示买入 , dp[i][1] 表示卖出, dp[i][2] 表示冷冻期
dp[0][0] = -prices[0];
for(int i = 1;i<n;i++)
{
dp[i][0] = max(dp[i-1][0],dp[i-1][1]-prices[i]);
dp[i][1] = max(dp[i-1][1],dp[i-1][2]);
dp[i][2] = dp[i-1][0] + prices[i];
}
return max(dp[n-1][2],dp[n-1][1]);
}
};
六、买卖股票的最佳时机含手续费
1.链接
714. 买卖股票的最佳时机含手续费 - 力扣(LeetCode)
2.描述
3.思路
4.参考代码
class Solution {
public:
int maxProfit(vector<int>& prices, int fee)
{
int n = prices.size();
vector<int> f(n,0);
auto g = f;
// f表示可买(没有股票) g表示不可买(已有股票)
g[0] = -prices[0];
for(int i = 1;i<n;i++)
{
f[i] = max(f[i-1],g[i-1]+prices[i]-fee);
g[i] = max(g[i-1],f[i-1]-prices[i]);
}
return max(f[n-1],g[n-1]);
}
};
七、买卖股票的最佳时机(最终版本)
1.链接
188. 买卖股票的最佳时机 IV - 力扣(LeetCode)
2.描述
3.思路
4.参考代码
class Solution {
public:
int maxProfit(int k, vector<int>& prices)
{
const int num = 0x3f3f3f3f;
int n = prices.size();
vector<vector<int>> f(n,vector<int>(k+1,-num));
auto g = f;
f[0][0] = -prices[0];
g[0][0] = 0;
for(int i = 1;i<n;i++)
{
for(int j = 0;j<=k;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 ret = g[n-1][0];
for(int i = 1 ; i<=k;i++)
{
ret = max(ret,g[n-1][i]);
}
return ret;
}
};
总结
本篇总结了关于多状态的动态规划,整理了一些简单的算法题,也有自己的分析和参考代码