1. 程式人生 > >[USACO09FEB]股票市場Stock Market

[USACO09FEB]股票市場Stock Market

題意簡述:

給定⼀個 D D 天的 S S 只股票價格矩陣,以及初始資⾦ M M

;每次買股票只能買某個股票價格的整數倍,可以不花錢,約定獲利不超過 500000 500000 。最⼤化你的 總獲利。

題目分析:

首先我們要知道此題的詳細意圖:每天都可以用你手中有的錢買入股票,數量不限,也可以賣出你自己的股票,所得的收益或價值已經在 D

S D*S 的矩陣中給出。要求在最後一天結束後得到的錢最多。

題解:

其實我們可以發現:對於每一天只要最大化你的收益就可以達成目的。然後問題就轉換為求每一天的股票交易情況了。又知道每個股票可以無限量的購買(當然價值和不多於手中的錢),顯然,就是一個完全揹包。

其實題目中的獲利不超過 500000 500000
已經暗中提示了DP等演算法的使用,因為給出一個不是由 i n t int l o n g long l o n g long 的資料範圍的改變一定是為陣列記憶體準備的。

⾸先每天結束之後剩下的錢儘量多肯定是最優的。
因為連續持有股票相當於每天買完以後,第⼆天
賣掉然後再買。所以就可以每天做⼀次完全揹包。
時間複雜度 O ( 700000 D S ) O(700000*D*S)

接下來就不再贅述了,其他部分會在程式碼中註明,看程式碼:

程式碼:

#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;
}