机器分配(17-17)

86 阅读2分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 2 月更文挑战」的第 17 天,点击查看活动详情

今天进行分组背包的学习。

机器分配

题目描述

总公司拥有 MM 台 相同 的高效设备,准备分给下属的 NN 个分公司。

各分公司若获得这些设备,可以为国家提供一定的盈利。盈利与分配的设备数量有关。

问:如何分配这M台设备才能使国家得到的盈利最大?

求出最大盈利值。

分配原则:每个公司有权获得任意数目的设备,但总台数不超过设备数 MM

输入格式

第一行有两个数,第一个数是分公司数 NN,第二个数是设备台数 MM

接下来是一个 N×MN×M 的矩阵,矩阵中的第 ii 行第 jj 列的整数表示第 ii 个公司分配 jj 台机器时的盈利。

输出格式

第一行输出最大盈利值;

接下 NN 行,每行有 22 个数,即分公司编号和该分公司获得设备台数。

答案不唯一,输出任意合法方案即可。

数据范围

1N10,1≤N≤10,
1M151≤M≤15

输入样例:

3 3
30 40 50
20 30 50
20 25 30

输出样例:

70
1 1
2 1
3 1

题目分析

本题是分组背包的问题。

首先我们将每家公司看作一个背包组,因为每家公司最终能够被分配的机器数量是固定且唯一的,因此对于分给第 ii 个公司的不同机器数量可以分别看作是一个背包组内的物品。

分给第 ii 家公司 kk 件设备,对应消耗 kk 体积,获得 wijw_{ij} 盈利。

初始状态为 f[0][0]=0f[0][0]=0,复杂度为 O(nm2)O(nm^2)

Accept代码 O(nm^2)

#include <bits/stdc++.h>

using namespace std;

const int N = 15, M = 20;

int n, m;
int w[N][M];
int f[N][M];
int way[N];

int main()
{
    cin >> n >> m;

    for (int i = 1; i <= n; i ++ )
        for (int j = 1; j <= m; j ++ )
            cin >> w[i][j];

    for (int i = 1; i <= n; i ++ )
        for (int j = 0; j <= m; j ++ )
            for (int k = 0; k <= j; k ++ )
                f[i][j] = max(f[i][j], f[i - 1][j - k] + w[i][k]);

    cout << f[n][m] << "\n";

    int j = m;
    for (int i = n; i; i -- )
        for (int k = 0; k <= j; k ++ )
            if (f[i][j] == f[i - 1][j - k] + w[i][k])
            {
                way[i] = k;
                j -= k;
                break;
            }

    for (int i = 1; i <= n; i ++ ) cout << i << ' ' << way[i] << "\n";

    return 0;
}