赞
踩
本文主要介绍了和DP相关的股票问题,分析比较简单,容易理解,适合刚接触DP的朋友们学习。
假设您有一个数组,第i个元素是第i天给定股票的价格。
如果只允许您最多完成一笔交易(即买入和卖出一股股票),请设计一种算法以找到最大的利润(卖出的价格-买入的价格)。
请注意,您不能在买股票之前卖出股票。
多组输入数据
每组数据第一行一个数n,(1≤n≤105)
接下来一行n个数表示股票的价格(1≤ai≤109)
每组数据一行一个数。
5
1 2 3 4 5
4
#include<iostream> #include<cstdio> using namespace std; int max(int n,int m){ if(n>=m) return n; return m; } int main(){ int n,a[100005]={}; long long buy,sell; while(~scanf("%d",&n)){ buy1=-1000000001,sell1=0; for(int i=1;i<=n;i++){ scanf("%d",&a[i]); } for(int i=1;i<=n;i++){ buy=max(buy,-a[i]); sell=max(sell,buy+a[i]); } printf("%lld\n",sell); } }
我们直接从DP的角度开始分析这个问题,首先看清题意,只能买入和卖出一股股票,并且卖出必须在买入之后完成。那么我们每一天的选择就是买或者不买或者卖,也就是有两种状态买buy和卖sell,而买入股票对应的就是花钱,我们最开始的钱为0,买入后就变会损失也就是-a[i],并且当天的总收益就为-a[i],也就是buy的值,卖出后则为收益也就是+a[i],并且当天的总收益就为buy+a[i]。所以我们就考虑当天买和之前买了(即与之前buy里的值进行比较)哪个收益更高,同时当天卖和之前已经卖了(即与之前sell里的值进行比较)哪个收益更高即可完成。
首先观察数据范围发现最终结果是可能超int的,所以对buy和sell的定义应为long long,然后是buy的初始值应该设置为负值而不是0,因为第一次买入的时候此时总收益就为负值。
假设您有一个数组,第i个元素是第i天给定股票的价格。
设计算法以找到最大的利润。您可以根据需要完成尽可能多的交易。
请注意,无法同时进行多项交易(即必须先出售股票才能再次购买)
多组输入数据
每组数据第一行一个数n,(1≤n≤105)
接下来一行n个数表示股票的价格(1≤ai≤109)
每组数据一行一个数
5
1 2 3 4 5
4
#include<iostream> #include<cstdio> using namespace std; int max(int n,int m){ if(n>=m) return n; return m; } int main(){ int n,a[100005]={}; long long buy,sell; while(~scanf("%d",&n)){ buy=-1000000001,sell=0; for(int i=1;i<=n;i++){ scanf("%d",&a[i]); } for(int i=1;i<=n;i++){ buy=max(buy,sell-a[i]); sell=max(sell,buy+a[i]); } printf("%lld\n",sell); } }
我们直接从上一问的思路继续分析,本题是要求利润最大并且可以完成任意多的交易(即可以买了又卖卖了再买),那我们还是同样分析,买了之后当天的总收益为sell-a[i](因为之前是处于卖了之后的状态所以用sell来减),然后卖了之后当天的总收益为buy-a[i](因为之前是处于买了之后的状态所以用buy来减),然后我们考虑每一天的情况即可。
buy = max(buy, sell-a[i])
sell = max(sell, buy+a[i])
还是一样需要注意数据类型的选择和buy的初始赋值,然后是sell最初值置0才能保证第一次买后总收益的正确性。
假设您有一个数组,第i个元素是第i天给定股票的价格。
设计算法以找到最大的利润。您最多可以完成两次交易。
请注意,无法同时进行多项交易(即必须先出售股票才能再次购买)
多组输入数据
每组数据第一行一个数n,(1≤n≤105)
接下来一行n个数表示股票的价格(1≤ai≤109)
每组数据一行一个数
5
1 2 3 4 5
4
#include<iostream> #include<cstdio> using namespace std; int max(int n,int m){ if(n>=m) return n; return m; } int main(){ int n,a[100005]={}; long long buy1,sell1,buy2,sell2; while(~scanf("%d",&n)){ buy1=-1000000001,sell1=0,buy2=-1000000001,sell2=0; for(int i=1;i<=n;i++){ scanf("%d",&a[i]); } for(int i=1;i<=n;i++){ buy1=max(buy1,-a[i]); sell1=max(sell1,buy1+a[i]); buy2=max(buy2,sell1-a[i]); sell2=max(sell2,buy2+a[i]); } printf("%lld\n",sell2); } }
我们还是延续思路继续分析,本题是要求利润最大并且只能完成两次交易,那我们还是同样分析,因为有两次交易,所以需要4个变量来存,第一次买了之后当天的总收益为-a[i](因为相当于之前没有卖出),然后第一次卖了之后当天的总收益为buy1-a[i](因为之前是处于第一次买了之后的状态所以用buy1来减),然后第二次买了之后当天的总收益为sell1-a[i](因为相当于之前有一次卖出),然后第二次卖了之后当天的总收益为buy2-a[i](因为之前是处于第二次买了之后的状态所以用buy2来减),然后我们考虑每一天的情况即可。
还是一样需要注意数据类型的选择和sell1、buy1、buy2的初始赋值,然后是sell1最初值置0才能保证第一次买后总收益的正确性。然后是对方程的理解,是怎么样实现的。
假设您有一个数组,第i个元素是第i天给定股票的价格。
设计算法以找到最大的利润。您最多可以完成k次交易。
请注意,无法同时进行多项交易(即必须先出售股票才能再次购买)
多组输入数据
每组数据第一行两个数n,k,(1≤n,k≤103)
接下来一行n个数表示股票的价格(1≤ai≤109)
每组数据一行一个数
5 2
1 2 3 4 5
4
#include<iostream> #include<cstdio> using namespace std; int max(int n,int m){ if(n>=m) return n; return m; } int main(){ int n,k,a[100005]={}; long long buy[1005],sell[1005]; while(~scanf("%d%d",&n,&k)){ for(int i=1;i<=n;i++){ scanf("%d",&a[i]); } for(int i=1;i<=k;i++){ buy[i]=-1000000001; sell[i]=0; } for(int i=1;i<=n;i++){ buy[1]=max(buy[1],-a[i]); sell[1]=max(sell[1],buy[1]+a[i]); for(int j=2;j<=k;j++){ buy[j]=max(buy[j],sell[j-1]-a[i]); sell[j]=max(sell[j],buy[j]+a[i]); } } printf("%lld\n",sell[k]); } }
我们还是相同思路继续分析,本题是要求利润最大并且只能完成k次交易,因为有k次交易,所以需要2k个变量来存,即用两个数组来存即可,第一次买了之后当天的总收益为-a[i](因为相当于之前没有卖出),然后第一次卖了之后当天的总收益为buy[1]-a[i](因为之前是处于第一次买了之后的状态所以用buy[1]来减),然后第二次买了之后当天的总收益为sell[1]-a[i](因为相当于之前有一次卖出),然后第二次卖了之后当天的总收益为buy[2]-a[i](因为之前是处于第二次买了之后的状态所以用buy[2]]来减),然后用一个从2-k的循环来实现此过程即可。
还是一样需要注意数据类型的选择和buy[],sell[]的初始赋值,然后是上文的AC代码的循环其实不用把buy[1]、sell[1]单独拿出来讨论的,只是更方便理解。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。