设m元钱,n项投资,函数fi(x)表示将x元投入第i项项目所产生的效益,i=1,2,…,n
问:如何分配这m元钱,使得投资的总效益最高?
动态规划问题一般分为两类:中间状态类和累积状态类。前者的参数是相同的,后者的参数不同,而且往往需要一个变量来进行遍历。这个问题以及最少货币数的问题都属于后者,最长公共子序列和最小路径和都属于前者。
int main() {
int m, n;//m元钱,n项投资
int i, j;
int tmp_m, tmp_F = 0, t = 0;//tem_m代表给第i个项目投入的钱数 0<=tmp<=j;tmp_F代表一次循环中的钱数
cin >> m >> n;
vector<vector<int>> f(n, vector<int>(m + 1));//f[i][x], 0<i<=n,0<=x<=m;
vector<vector<int>> F(n, vector<int>(m + 1)), Max(n, vector<int>(m + 1));//F[i][x],将x元钱投入到前i个项目上最大的收益
vector<int>max(n);
for (i = 0; i < n; ++i) {
f[i][0] = 0;
}
for (i = 0; i < n; ++i) {
for (j = 1; j < m + 1; ++j) {//j从1开始,也就是从f[0][1]开始
cin >> f[i][j];
}
}
for (j = 0; j < m + 1; ++j) {
F[0][j] = f[0][j];
Max[0][j] = j;//不要忘了这一步
}
for (i = 1; i < n; ++i) {
for (j = 0; j < m + 1; ++j) {
for (tmp_m = 0; tmp_m <= j; ++tmp_m) {
tmp_F = F[i - 1][j - tmp_m] + f[i][tmp_m];
if (tmp_F > F[i][j]) {
F[i][j] = tmp_F;
Max[i][j] = tmp_m;
}
}
}
}
//采用从后往前推的方式。
max[n - 1] = Max[n - 1][m];
for (i = n - 2; i >= 0; --i) {
t = 0;
for (j = n - 1; j > i; --j) {
t += max[j];
}
max[i] = Max[i][m - t];
}