top1编程
← 返回题目
题解

【提高】机器分配

1 条题解

  • 0
    @ 2026-7-31 19:32:38

    解题思路

    把 M 台设备分给 N 个公司,每个公司分到 j 台有对应盈利,求最大总盈利和分配方案。

    思路:动态规划(分组背包)。

    设 dp[i][j] = 前 i 个公司分配 j 台设备的最大盈利。

    对第 i 个公司,可以分给它 k 台(0 到 j),剩下的 j-k 台给前 i-1 个公司:

    dp[i][j] = max(dp[i-1][j-k] + profit[i][k]),k 从 0 到 j

    怎么回溯分配方案? 用 path[i][j] 记录 dp[i][j] 达到最优时第 i 个公司分了多少台。算完后从最后一个公司往前回溯,得到每个公司的分配数。

    举例:3 公司 3 台设备

    • DP 算出最大盈利 70
    • 分配:每个公司 1 台

    参考代码

    #include <iostream>
    using namespace std;
    
    int profit[15][15];
    int dp[15][15];
    int path[15][15];
    
    int main() {
        int n, m;
        cin >> n >> m;
    
        for (int i = 1; i <= n; i++) {
            for (int k = 1; k <= m; k++) cin >> profit[i][k];
        }
    
        for (int i = 1; i <= n; i++) {
            for (int j = 1; j <= m; j++) {
                int mx = 0, bestK = 0;
                for (int k = 0; k <= j; k++) {  // 第 i 公司分 k 台
                    int cur = dp[i - 1][j - k] + profit[i][k];
                    if (cur > mx) {
                        mx = cur;
                        bestK = k;
                    }
                }
                dp[i][j] = mx;
                path[i][j] = bestK;
            }
        }
    
        // 回溯分配
        int assign[15];
        int rem = m;
        for (int i = n; i >= 1; i--) {
            assign[i] = path[i][rem];
            rem -= assign[i];
        }
    
        cout << dp[n][m] << endl;
        for (int i = 1; i <= n; i++) {
            cout << i << " " << assign[i] << endl;
        }
        return 0;
    }
    

    复杂度分析

    • 时间复杂度:O(N×M²),枚举公司和设备数
    • 空间复杂度:O(N×M),DP 数组
    • 1