算法实践7 投资问题

问题:

\(m\)万元钱,\(n\)项投资,函数\(f_i(x)\)表示将\(x\)万元投入到第\(i\)项项目所产生的效益,\(i=1,2,\dots,n\)。问:如何分配这\(m\)万元,使得投资的总收益最高。

解析

\(dp[i][j]\)为在前\(i\)个项目中投入\(j\)元能获得的最大收益。当\(i = 1\)时,我们从\(0\)推到\(1\)是显然正确的。那么当前一个项目在花\(m_1\)万元的最优解确定下来之后,我们能够枚举当前项目花\(m_2\)万元,从而在有向图上覆盖到所有合法的点,最终处理出最优解。

设计

for 枚举项目
    for 枚举花费
        for 枚举第i个项目花费q
            dp[i][j] = max(dp[i][j], dp[i - 1][j - q] + w[i][q]);

分析

三层循环,时间复杂度\(O(nm^2)\)

源码

https://github.com/Sstee1XD/Algorithm_homework/tree/main/实验7 投资问题

#include <bits/stdc++.h>

using namespace std;

#define endl "\n"

const int N = 1e3 + 7;

int w[N][N];
int dp[N][N];

int n, m, k;

void solve() {
    cin >> n >> k >> m;  // n个项目,每个项目能投资0~k,资金m
    for (int i = 1; i <= n; ++i) {
        for (int j = 1; j <= k; ++j) {
            cin >> w[i][j];
        }
    }
    for (int i = 1; i <= n; ++i) {
        for (int j = 1; j <= m; ++ j) {
            if (j > i * k) break;
            dp[i][j] = 0;
        }
    }
    for (int i = 1; i <= n; ++i) { // 第i个项目
        for (int j = 1; j <= m; ++j) { // 总共花费j
            if (j > i * k) break;
            for (int q = min(k, j); q >= 0; --q) { // 第i个项目花费q
                dp[i][j] = max(dp[i][j], dp[i - 1][j - q] + w[i][q]);
            }
        }
    }
    if (m > n * k) m = n * k; // 特判,当然也可以在转移方程时多一步
    cout << dp[n][m] << endl;
}

int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);cout.tie(nullptr);
    int t = 1;
    while (t--) solve();
    return 0;
}
/*
5 5 10
1 2 3 4 5
11 12 13 14 15
0 5 10 15 20
2 10 30 32 40
20 21 22 23 24
*/
posted @ 2021-06-22 21:04  stff577  阅读(110)  评论(0)    收藏  举报