问题描述
我们来玩一个大富翁的游戏,在地图上有N个连续的城市,城市对某件商品的售价为[V1,V2,V3…VN],你作为未来的大富翁看到其中的商机,打起了倒卖商品赚取差价的主意。
约束条件:你只能顺序从第一个城市出发,不能走回头路,每次只能交易一件商品,再下次买入商品后必须卖掉之前买入的商品,求你能赚取的最大财富。比如:城市商品售价为[1,9,2,3,8],最大财富为(9-1)+(8-2)=14;城市商品售价为[9,8,3,2,1],最大财富为0,因为你买啥都无法赚钱。
问题分析
从给出的事例中可以分析出来从第一个城市开始买进后与第二个城市售价相比可能会有三种情况:
1.第二个城市售价低于第一个城市;
2.第二个城市高于第一个城市,并且后面没有比第二个城市售价高;
3.第二个城市高于第一个城市,但后面还有城市高于第二个城市;
综上所述主要是这三种情况。
算法实现
用一个数组存储所有城市的售价,一个str指针指向头,另一个ptr指针指向str的下一个,首先找到较小的数第一次买入,然后开始做对比。ptr的存的数如果小于str,ptr指向下一个;ptr存的数大于str,ptr与ptr+1做对比,如果ptr+1小于ptr,说明这时卖出最划算,然后计算收益。如果ptr+1大于ptr,ptr继续向后指,直到ptr大于ptr+1。每次计算完收益,str都指向ptr+1,从而开始计算下一次收益 。下一次受一开始时,str指向的数与str+1做对比,如果str+1小于str则当前str向后移指向str+1,依次向后做对比,直到str小于str+1,然后从下一个地址作为ptr的起点,开始选取ptr。算法如图:
ptr大于str直接算利润
继续开始下一次,先寻找较小的数作为str,买入
然后寻找较大的数作为ptr,ptr大于str,ptr与它的下一个地址中的值作比较。
直到ptr+1的值小于ptr,结束,计算利润。
c语言程序代码实现:
#include<stdio.h>
#include<stdlib.h>
int main()
{
int num = 0;//城市个数
int sell[100] = { 0 };//每个城市的售价
int income = 0;//收入
int *str = sell;//头指针
int *ptr = str + 1;//尾指针
scanf_s("%d", &num);
for (int i = 0; i < num; i++)
{
scanf_s("%d", &sell[i]);
}
while (*str > *(str + 1)) //判断后面有没有比目前更小的数,有的话替换到较小的数买入,使利益最大化
{
str++;
if (*str == 0)
{
break;
}
}
ptr = str + 1;//更新 ptr
while (ptr < (&sell[num]))
{
if (*ptr > *str)
{
while (*ptr < *(ptr + 1)) //判断后面有没有比目前更大的数,有的话替换
{
ptr++;
}
income = income + (*ptr - *str);
str = ptr + 1;//开始计算下一次收益
while (*str > *(str + 1)) //判断后面有没有比目前更小的数,有的话替换到较小的数买入,是利益最大化
{
str++;
if (*str == 0)
{
break;
}
}
ptr = str + 1;//每次计算完收益,两个指针均往后移动,以便计算开始计算下一次收益
}
else
{
ptr++;
}
}
printf("%d\n", income);
system("pause");
return 0;
}
测试结果:
有不对的地方希望大家批评指正!