今天刷到一道状态分析把我搞的稀里糊涂的题目,故提笔记之
题目如下
思路如下
首先对其状态进行分析。在任意一天结束时,只可能有三种状态
- 手里有一支股票
- 手里没股票,在这天结束后处于冷冻期
- 手里没股票,这天结束后也不处于冷冻期间
然后我们对这三个状态进行分析。判断他们需要从哪个状态转移过来。然后对其进行编程即可。
重点来了:这状态转移分析弄得我脑子一团浆糊。。。
首先对状态1分析:当天结束后,手里有一支股票,那么有两种可能,是由前一天结束手里有一支股票的状态转移过来或者前一天结束手里没股票然后在今天买的股票。取这两种情况的最大值即可
对状态2分析:当天结束,手里没股票并且今天结束后处于冷冻期,那么它今天必然是把股票卖出去了,所以肯定从前一天有股票的状态转移过来的。
对状态3分析:当天结束,手里没股票且不处于冷冻期的话,南无有两种可能,从前一天没股票且不处于冷冻期的状态下转移过来或者从前一天没股票处于冷冻期的状态转移过来。
逻辑代码如下
#include <vector>
#include <iostream>
#include <algorithm>
using namespace std;
class Solution {
public:
int maxProfit(vector<int>& prices) {
int n = prices.size();
vector<vector<int>> dp(n, vector<int>(3,0));//0表示没股票,1表示有股票,3表示没股票,且处于冷冻期中
for(int i=0; i<n; i++){
if(i==0){
dp[i][0] = 0;
dp[i][1] = -1*prices[i];
}else{
dp[i][0] = dp[i-1][1]+prices[i];
dp[i][1] = max(dp[i-1][1], dp[i-1][2]-prices[i]);
dp[i][2] = max(dp[i-1][0], dp[i-1][2]);
}
}
return max(dp[n-1][0], dp[n-1][2]);
}
};
int main(){
vector<int> v{1,2,4};
cout<<Solution().maxProfit(v);
return 0;
}
总结
也做了这么多动态规划的题目了。我感觉动态规划最终要的还是要确定好状态量,且这个状态量可能不止一个。然后找出先后状态之间的关系,并且列出状态转移方程。而且我发现,能动态规划的题目,一般都能记忆化搜索,两者有异曲同工之妙。动态规划是要不断的利用到先前的状态进一步得出后续状态。而记忆化搜索则是将之前搜索出的结果保存下来,进而减少后续的搜索量。但是动态规划不管从时间还是空间复杂度上都是要比记忆化搜索要高出不少的,因为动态规划是一个自底向上的过程,我们不需要递归占用栈空间。且空间复杂度上我们可以对其进行优化。
续
若彻底理解了上面的思路,可以试试下面这道题