百炼4121 股票买卖
做法
一个很有意思的动态规划问题,参照了别人的答案,才理解做法,注意点如下:
- 建立两个dp数组,命名为dp1,dp2
其中dp1[i]代表到第i天为止卖出的股票所能获得的最大利润
而dp2[i]代表到从第i天开始买进股票所能获得的最大利润
分别正向与反向遍历数组,求得dp1,dp2
注意:
这种做法的可以获得正确答案的原因是:要获得dp1[i]的利润,买入的那一天一定小于等于i,而要获得dp2[i]的利润,卖出的那一天一定大于等于i
所以,最大的利润就是max{dp1[i]+dp2[i] ,i=1…n}咯! - 注意求dp1[i]时要涉及dp1[i-1],求dp2[i]时要涉及dp2[i+1],所以数组下标从1到n比较好搞
- 最大值和最小值的设定就不墨迹了
代码如下
//
#include <cstdio>
#include <algorithm>
using namespace std;
int num_group;
int num;
int stocks[100010];
int dp1[100010];
int dp2[100010];
int main()
{
scanf("%d", &num_group);
for (int i = 0; i < num_group; i++)
{
scanf("%d", &num);
for (int j = 1; j <= num; j++)
{
scanf("%d", &stocks[j]);
}
fill(dp1, dp1 + 100010, 0);
fill(dp2, dp2 + 100010, 0);
dp1[0] = -0x7fffffff;
int minnum = 0x7fffffff;
for (int j = 1; j <= num; j++)
{
minnum = min(stocks[j], minnum);
dp1[j] = max(dp1[j - 1], stocks[j] - minnum);
}
dp2[num + 1] = -0x7fffffff;
int maxnum = -0x7fffffff;
for (int j = num; j >= 1; j--)
{
maxnum = max(stocks[j], maxnum);
dp2[j] = max(dp2[j + 1], maxnum - stocks[j]);
}
int result = 0;
for (int j= 1; j <= num; j++)
{
result = max(result, dp1[j] + dp2[j]);
}
printf("%d\n", result);
}
return 0;
}
刚开始学算法,欢迎交流