题意:有S种股票,我们已经知道每一天每一种股票的价格。一共有d天,一开始拥有的钱为m,求最后总共能够拥有多少钱。
Sol:
一开始我十分沙茶。。
我们设dp[i]表示第i天能够拥有的最大价值。于是我们枚举上一次买股票时间j,然后以dp[j]为容量做完全背包。这样的总时间复杂度为O(msd^2).显然是超时的。
事实上,我们只需从第i-1天进行转移即可。因为若有若干天没有买股票,也同样可以通过完全背包转移,进行考虑后是很显然的。
于是总的时间复杂度变为O(msd),要求常数优化到位。
Code:
#include <cstdio>
#include <cstring>
#include <cctype>
#include <iostream>
#include <algorithm>
using namespace std;
#define S 51
#define D 11
#define M 500010
int p[D][S], best[D], dp[M];
int tmp[S], top;
#define _max(a, b) ((a)>(b)?(a):(b))
int main() {
int s, d, m;
scanf("%d%d%d", &s, &d, &m);
int i, j, k;
for(i = 1; i <= s; ++i)
for(j = 1; j <= d; ++j)
scanf("%d", &p[j][i]);
best[1] = m;
for(i = 2; i <= d; ++i) {
top = 0;
for(j = 1; j <= s; ++j)
if (p[i][j] > p[i - 1][j])
tmp[++top] = j;
for(k = 1; k <= best[i - 1]; ++k)
dp[k] = k;
for(j = 1; j <= top; ++j)
for(k = p[i - 1][tmp[j]]; k <= best[i - 1]; ++k)
dp[k] = _max(dp[k], dp[k - p[i - 1][tmp[j]]] + p[i][tmp[j]]);
best[i] = _max(best[i], dp[best[i - 1]]);
}
printf("%d", best[d]);
return 0;
}