题意简述:

给定⼀个 D D D天的 S S S只股票价格矩阵,以及初始资⾦ M M M;每次买股票只能买某个股票价格的整数倍,可以不花钱,约定获利不超过 500000 500000 500000。最⼤化你的 总获利。

题目分析:

首先我们要知道此题的详细意图:每天都可以用你手中有的钱买入股票,数量不限,也可以卖出你自己的股票,所得的收益或价值已经在 D S D*S DS的矩阵中给出。要求在最后一天结束后得到的钱最多。

题解:

其实我们可以发现:对于每一天只要最大化你的收益就可以达成目的。然后问题就转换为求每一天的股票交易情况了。又知道每个股票可以无限量的购买(当然价值和不多于手中的钱),显然,就是一个完全背包。

其实题目中的获利不超过 500000 500000 500000已经暗中提示了DP等算法的使用,因为给出一个不是由 i n t int int l o n g long long l o n g long long 的数据范围的改变一定是为数组内存准备的。

⾸先每天结束之后剩下的钱尽量多肯定是最优的。
因为连续持有股票相当于每天买完以后,第⼆天
卖掉然后再买。所以就可以每天做⼀次完全背包。
时间复杂度 O ( 700000 D S ) O(700000*D*S) O(700000DS)

接下来就不再赘述了,其他部分会在代码中注明,看代码:

代码:

#include<cstdio>
#include<cmath>
#include<cstring>
using namespace std;
int a[61][21],f[500005];
int main()
{
	int s,d,m;
	scanf("%d%d%d",&s,&d,&m);
	for(int i=1;i<=s;i++)
	{
		for(int j=1;j<=d;j++)
		{
			scanf("%d",&a[i][j]);
		}
	}//以上不需要解释
	for(int k=2;k<=d;k++)
	{
		memset(f,0,sizeof(f));
		int maxx=0;
		for(int i=1;i<=s;i++)
		{
			for(int j=a[i][k-1];j<=m;j++)//每次循环到前一天当前位置的股票交易价格。
			{
				f[j]=fmax(f[j],f[j-a[i][k-1]]+a[i][k]-a[i][k-1]);//第一种情况是不买,第二种就是买:要价格减去买入所花的钱再加上今天和昨天的价格差,因为如果不卖出相当于卖出再买入
				maxx=fmax(f[j],maxx);//取出一天股票的最大值
			}
		}
		m+=maxx;//累加收益
	}
	printf("%d",m);
	return 0;
}

以上是原题P2938的解法

但是观察这道题仅仅是把输入顺序和数据范围微调,且没有实质上的改变,所以

#include<cstdio>
#include<cmath>
#include<cstring>
using namespace std;
int a[105][105],f[10005];
int main()
{
	int s,d,m;
	scanf("%d%d%d",&d,&s,&m);
	for(int i=1;i<=d;i++)
	{
		for(int j=1;j<=s;j++)
		{
			scanf("%d",&a[j][i]);
		}
	}//以上不需要解释
	for(int k=2;k<=d;k++)
	{
		memset(f,0,sizeof(f));
		int maxx=0;
		for(int i=1;i<=s;i++)
		{
			for(int j=a[i][k-1];j<=m;j++)//每次循环到前一天当前位置的股票交易价格。
			{
				f[j]=fmax(f[j],f[j-a[i][k-1]]+a[i][k]-a[i][k-1]);//第一种情况是不买,第二种就是买:要价格减去买入所花的钱再加上今天和昨天的价格差,因为如果不卖出相当于卖出再买入
				maxx=fmax(f[j],maxx);//取出一天股票的最大值
			}
		}
		m+=maxx;//累加收益
	}
	printf("%d",m);
	return 0;
}

即可,这里需要注意f数组要开成题目保证不超过的范围,而不是读入的m的范围