股票买卖
- 股票买卖 1
- 这道题就是求max {ai−aj|j<i}
- 股票买卖 2
- 股票买卖 3
- 方法一:前后缀拆分dp
- 怎么想到的?
- 方法二:状态机dp
- f[0/1][i]表示只考虑前i支股票且手头有/没有股票的最大收益
- 股票买卖 4
- 考虑前 i 天的股票,第 i 天的 决策 是 k,且完成的 完整交易数 为 j 的方案
- 股票买卖 5
- 股票买卖 6
股票买卖 1
原题链接
这道题就是求max {ai−aj|j<i}
#include<iostream>
using namespace std;
const int N = 1e5+10;
int a[N];
int n;
int mi = 0x3f3f3f3f;
int ans = 0;
int main()
{
cin >> n;
for(int i = 1; i <= n; i++)
{
cin >> a[i];
mi = min(a[i],mi);
if(i!=1)
{
ans = max(ans,a[i]-mi);
}
}
cout << ans;
return 0;
}
股票买卖 2
原题链接
#include<iostream>
using namespace std;
const int N = 1e5+10;
int a[N];
int n;
int main()
{
cin >> n;
int ans = 0;
for(int i = 1; i <= n; i++)
{
cin >> a[i];
if(i!=1)
ans = ans + max(0,a[i]-a[i-1]);
}
cout << ans;
return 0;
}
股票买卖 3
方法一:前后缀拆分dp
怎么想到的?
首先我们想的是,先按着第一道题的方法,遍历一边数组,得到买卖一次的最大值,然后再遍历一次,得到买卖第二次的最大值,但是这个是不行的。
原因是,这道题要求我们,第二次买之前,第一次的必须卖出去
所以,我们想到的是开两个dp数组
#include <iostream>
#include <algorithm>
using namespace std;
const int N = 100010;
int arr[N];
int dp[N];
int rdp[N];
int n;
int main()
{
cin >> n;
for (int i = 0; i < n; i++) {
cin >> arr[i];
}
int low = 9999999;
int ans = 0;
for (int i = 0; i < n; i++) {
low = min(low, arr[i]);
ans = max(ans, arr[i] - low);
dp[i] = ans;
}
int high = 0;
ans = 0;
for (int i = n - 1; i >= 0; i--) {
high = max(high, arr[i]);
ans = max(ans, high - arr[i]);
rdp[i] = ans;
}
ans = 0;
for (int i = 0; i < n; i++) {
ans = max(ans,dp[i] + rdp[i]);
}
cout << ans << endl;
return 0;
}
方法二:状态机dp
f[0/1][i]表示只考虑前i支股票且手头有/没有股票的最大收益
#include<iostream>
#include<cstdio>
#include<cstring>
typedef long long ll;
#define MAXN 200011
ll f[5][MAXN];
int main()
{
memset(f,0xcf,sizeof f);
ll n;
scanf("%lld",&n);
f[0][0]=0;
for(ll i=1;i<=n;++i)
{
ll x;
scanf("%lld",&x);
f[0][i]=f[0][i-1];
f[1][i]=std::max(f[1][i-1],f[0][i-1]-x);
f[2][i]=std::max(f[2][i-1],f[1][i-1]+x);
f[3][i]=std::max(f[3][i-1],f[2][i-1]-x);
f[4][i]=std::max(f[4][i-1],f[3][i-1]+x);
}
printf("%lld",std::max(f[0][n],std::max(f[2][n],f[4][n])));
return 0;
}
股票买卖 4
原题链接
考虑前 i 天的股票,第 i 天的 决策 是 k,且完成的 完整交易数 为 j 的方案
#include <iostream>
#include <cstring>
using namespace std;
const int N = 1e5 + 10, M = 110;
int n, k;
int w[N];
int f[N][M][2];
int main()
{
cin >> n >> k;
for (int i = 1; i <= n; ++ i) cin >> w[i];
memset(f, -0x3f, sizeof f);
f[0][0][0] = 0; //初始状态f[0][0][0]
for (int i = 1; i <= n; ++ i)
{
for (int j = 0; j <= k; ++ j)
{
f[i][j][0] = f[i - 1][j][0];
if (j) f[i][j][0] = max(f[i][j][0], f[i - 1][j - 1][1] + w[i]);
f[i][j][1] = max(f[i - 1][j][1], f[i - 1][j][0] - w[i]);
}
}
int res = 0;
for (int j = 0; j <= k; ++ j) res = max(res, f[n][j][0]); //目标状态f[n][j][0]
cout << res << endl;
return 0;
}
#include <iostream>
#include <cstring>
using namespace std;
const int N = 1e5 + 10, M = 110;
int n, k;
int w[N];
int f[2][M][2];
int main()
{
cin >> n >> k;
for (int i = 1; i <= n; ++ i) cin >> w[i];
memset(f, -0x3f, sizeof f);
f[0][0][0] = 0; //初始状态f[0][0][0]
for (int i = 1; i <= n; ++ i)
{
for (int j = 0; j <= k; ++ j)
{
f[i & 1][j][0] = f[(i - 1) & 1][j][0];
if (j) f[i & 1][j][0] = max(f[i & 1][j][0], f[(i - 1) & 1][j - 1][1] + w[i]);
f[i & 1][j][1] = max(f[(i - 1) & 1][j][1], f[(i - 1) & 1][j][0] - w[i]);
}
}
int res = 0;
for (int j = 0; j <= k; ++ j) res = max(res, f[n & 1][j][0]); //目标状态f[n][j][0]
cout << res << endl;
return 0;
}
股票买卖 5
#include <iostream>
#include <cstring>
using namespace std;
const int N = 1e5 + 10, M = 110;
int n, k;
int w[N];
int f[N][M][2];
int main()
{
cin >> n >> k;
for (int i = 1; i <= n; ++ i) cin >> w[i];
memset(f, -0x3f, sizeof f);
f[0][0][0] = 0; //初始状态f[0][0][0]
for (int i = 1; i <= n; ++ i)
{
for (int j = 0; j <= k; ++ j)
{
f[i][j][0] = f[i - 1][j][0];
if (j) f[i][j][0] = max(f[i][j][0], f[i - 1][j - 1][1] + w[i]);
f[i][j][1] = max(f[i - 1][j][1], f[i - 1][j][0] - w[i]);
}
}
int res = 0;
for (int j = 0; j <= k; ++ j) res = max(res, f[n][j][0]); //目标状态f[n][j][0]
cout << res << endl;
return 0;
}
#include <iostream>
#include <cstring>
using namespace std;
const int N = 1e5 + 10, M = 110;
int n, k;
int w[N];
int f[2][M][2];
int main()
{
cin >> n >> k;
for (int i = 1; i <= n; ++ i) cin >> w[i];
memset(f, -0x3f, sizeof f);
f[0][0][0] = 0; //初始状态f[0][0][0]
for (int i = 1; i <= n; ++ i)
{
for (int j = 0; j <= k; ++ j)
{
f[i & 1][j][0] = f[(i - 1) & 1][j][0];
if (j) f[i & 1][j][0] = max(f[i & 1][j][0], f[(i - 1) & 1][j - 1][1] + w[i]);
f[i & 1][j][1] = max(f[(i - 1) & 1][j][1], f[(i - 1) & 1][j][0] - w[i]);
}
}
int res = 0;
for (int j = 0; j <= k; ++ j) res = max(res, f[n & 1][j][0]); //目标状态f[n][j][0]
cout << res << endl;
return 0;
}
作者:一只野生彩色铅笔
链接:https://www.acwing.com/solution/content/55037/
来源:AcWing
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
股票买卖 6
原题链接
#include <iostream>
const int N=100010;
int n,f;
int data[N];
int dp[2][N];
int main()
{
scanf("%d %d\n",&n,&f);
for(int i=1;i<=n;i++)
scanf("%d",&data[i]);
dp[1][1]=-data[1];
for(int i=2;i<=n;i++)
{
dp[0][i]=std::max(dp[0][i-1],data[i]+dp[1][i-1]-f);
dp[1][i]=std::max(dp[1][i-1],dp[0][i-1]-data[i]);
}
std::cout<<dp[0][n];
return 0;
}