首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >可获得的最大利润-买卖

可获得的最大利润-买卖
EN

Stack Overflow用户
提问于 2017-01-03 20:06:25
回答 3查看 1.1K关注 0票数 2

假设我们有一个准确的预测梅西的价格一段时间的N天。这个预测是作为一个列表给出的,在这个列表中,p_i表示球员在日i中的价格。Bob计划在此期间进行多个连续的事务,但一次不能拥有多个Messi,因此需要在再次购买他之前卖掉他。

鲍勃从一个有限的预算B开始,不能买一个比他负担得起的更贵的梅西。当然,鲍勃可以在他的预算中增加他从买卖他的梅西斯中获得的任何利润。对他来说幸运的是,有些时候,他从事先打开一个随机的礼品包开始使用梅西。

最后,鲍勃只想得到尽可能多的利润,并出售最后梅西。

输入格式:

在输入文件的第一行,您将找到3个整数,N、B和M。

N表示Bob预测梅西价格的天数。B代表鲍勃的初步预算。M既可以是0,也可以是1;如果Bob开始时没有初始的Messi,则为0;如果他确实以初始的Messi开始出售,则为1。

在下一行中,您将找到N个整数: p1、p2、…,pN由一个空格分隔,其中pi代表梅西在第一天的价格。

给出的测试案例

测试1

7 5 0

20 10 30 5 10 10 20

正确答案: 15

说明:鲍勃最初的预算是5英镑,而不是最初的梅西。他不能买任何梅西,直到他的价格降到5,所以他的利润只有(20-5) = 15。

测试2

7 0 1

20 10 50 80 60 20 10

正确答案: 90

说明:鲍勃的初始预算为0,而梅西的初始预算为1美元。因此,他以20英镑的价格卖掉了最初的梅西,以10美元买回了他,然后以80英镑的价格卖掉了他,所以他的利润是20 + (80-10) = 90。

这个问题是在一次面试中给我的,我一直未能找到一个有效的解决方案。同时,我在这个问题上发现了一些更简单的变体,比如买卖一股最多两倍的最大利润,但是我在理解如何使思想适应我的问题方面没有成功。

到目前为止,我只想出了一个强力的解决方案,远远超出了给我的时间限制( C++是0.1秒,其中1 <= N <= 10^5)。

我正在寻找一种解决方案和思考这类问题的方法,我似乎找不到正确的方法来思考这个问题。

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2017-01-03 20:26:45

我们可以使用动态规划。

  1. 让我们将f0(i)定义为如果在一天开始时没有i,我们可以获得的最大预算。如果我们抓住了他,让f1(i)成为同样的价值。
  2. i = 0的基值取决于我们一开始是否有他。
  3. 过渡情况如下:
代码语言:javascript
复制
- We can go from `i` to `i + 1` and do nothing
- If we have Messi, we can sell him (setting `f0(i + 1) = max(f0(i + 1), f1(i) + price(i))`)
- If we don't have him and our budget is big enough, we can buy him  (doing `f1(i + 1) = max(f1(i + 1), f0(i) - price(i))`)

  1. 答案是f0(n) (这意味着所有的日子都过去了,我们没有他)。

这个解决方案显然需要线性的时间和空间,所以任何合理的C++实现都应该适合您的需求。

票数 2
EN

Stack Overflow用户

发布于 2017-01-03 20:28:19

首先,简化问题是将梅西最初的“礼物”以梅西最初的价格折算成等额的钱。用户可以选择要么买回梅西,要么在一开始就不买。

之后,你会发现第一个价格足够低的用户购买一个梅西,并放弃之前的每一个预测。然后,求出所有预测价格的局部极小和局部最大值,然后在所有最小值上买入,在所有最大值上卖出,但记住,如果局部极小值是最后的预测值,则不要回购。

这将解决O(N)中的问题。

编辑:通过序列的2度差可以找到局部最小或最大值:

代码语言:javascript
复制
d[i] = p[i+1] - p[i]
d2[i] = d[i] - d[i-1]

如果是d2[i] > 0,则是局部极小;如果是d2[i] < 0,则为局部极大。显然会有一些边界条件,你需要处理,但它不应该太难。

票数 1
EN

Stack Overflow用户

发布于 2017-01-03 22:41:48

代码语言:javascript
复制
// input
long predictionLength;
long budget;
bool startWithMessi;
long prediction[MAX_PREDICTION_LENGTH];

// output
long profit;

ifstream fin;
fin.open( DATA_FILE_NAME );
fin >> predictionLength >> budget >> startWithMessi;
for( long day = 0; day < predictionLength; day++ )
  fin >> prediction[day];
fin.close();

long money = budget;
bool messi = startWithMessi;
long dayIndex = 0;
while( dayIndex < predictionLength )
{
  if( messi )
  {
    if( dayIndex == predictionLength - 1
      || prediction[dayIndex] > prediction[dayIndex + 1] )
    {
      money += prediction[dayIndex];
      messi = false;
    }
  }
  else
    if( dayIndex < predictionLength - 1
      && prediction[dayIndex] < prediction[dayIndex + 1]
      && money >= prediction[dayIndex] )
    {
      money -= prediction[dayIndex];
      messi = true;
    }
  dayIndex++;
}

profit = money - budget;

cout << profit << endl;
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/41451482

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档