题目链接
给定一个长度为 N 的数组,数组中的第 i 个数字表示一个给定股票在第 i 天的价格。
设计一个算法来计算你所能获取的最大利润。你可以尽可能地完成更多的交易(多次买卖一支股票)。
注意:你不能同时参与多笔交易(你必须在再次购买前出售掉之前的股票)。
输入格式
第一行包含整数 NN,表示数组长度。
第二行包含 NN 个不大于 1000010000 的正整数,表示完整的数组。
输出格式
输出一个整数,表示最大利润。
数据范围
1≤N≤1051≤N≤105
输入样例1:
6
7 1 5 3 6 4
输出样例1:
7
输入样例2:
5
1 2 3 4 5
输出样例2:
4
样例解释
样例1:在第 2 天(股票价格 = 1)的时候买入,在第 3 天(股票价格 = 5)的时候卖出, 这笔交易所能获得利润 = 5-1 = 4 。随后,在第 4 天(股票价格 = 3)的时候买入,在第 5 天(股票价格 = 6)的时候卖出, 这笔交易所能获得利润 = 6-3 = 3 。共得利润 4+3 = 7。
样例2:在第 1 天(股票价格 = 1)的时候买入,在第 5 天 (股票价格 = 5)的时候卖出, 这笔交易所能获得利润 = 5-1 = 4 。注意你不能在第 1 天和第 2 天接连购
买股票,之后再将它们卖出。因为这样属于同时参与了多笔交易,你必须在再次购买前出售掉之前的股票。
我的代码:
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
const int maxn=1e5+10;
int f[maxn][5];
int a[maxn];
int n,ans;
void dp(){
f[0][1]=-100000;
f[0][0]=0;
for(int i=1;i<=n;i++){
f[i][0]=max(f[i-1][0],f[i-1][1]+a[i]);
f[i][1]=max(f[i-1][0]-a[i],f[i-1][1]);
}
return;
}
int main(){
cin>>n;
for(int i=1;i<=n;i++)
cin>>a[i];
dp();
int ans=f[n][0];
cout<<ans<<endl;
return 0;
}
我的思路:
显然用0表示当前未处于购买状态,1表示当前处于购买状态,那么状态转移方程自然而然的得到:
f[i][0] = max ( f[i-1][0] , f[i-1][1] + a[i] );
f[i][1] = max ( f[i-1][0] - a[i],f[i-1][1] );
需要注意的是当前i处买入是-a[i],卖掉是+a[i],当前点买入那么当前点的状态是1,当前点卖出,当前点的状态时0
带入i=1时可以发现f[0][0]必须得是零,f[0][1]必须是负无穷,其他点可以迭代产生,可以说只要定义这两个点其他店不用管,自己就可以生成,但一般规律是三个值,正负无穷,0。