开启掘金成长之旅!这是我参与「掘金日新计划 · 2 月更文挑战」的第 17 天,点击查看活动详情
今天进行分组背包的学习。
机器分配
题目描述
总公司拥有 台 相同 的高效设备,准备分给下属的 个分公司。
各分公司若获得这些设备,可以为国家提供一定的盈利。盈利与分配的设备数量有关。
问:如何分配这M台设备才能使国家得到的盈利最大?
求出最大盈利值。
分配原则:每个公司有权获得任意数目的设备,但总台数不超过设备数 。
输入格式
第一行有两个数,第一个数是分公司数 ,第二个数是设备台数 ;
接下来是一个 的矩阵,矩阵中的第 行第 列的整数表示第 个公司分配 台机器时的盈利。
输出格式
第一行输出最大盈利值;
接下 行,每行有 22 个数,即分公司编号和该分公司获得设备台数。
答案不唯一,输出任意合法方案即可。
数据范围
输入样例:
3 3
30 40 50
20 30 50
20 25 30
输出样例:
70
1 1
2 1
3 1
题目分析
本题是分组背包的问题。
首先我们将每家公司看作一个背包组,因为每家公司最终能够被分配的机器数量是固定且唯一的,因此对于分给第 个公司的不同机器数量可以分别看作是一个背包组内的物品。
分给第 家公司 件设备,对应消耗 体积,获得 盈利。
初始状态为 ,复杂度为 。
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;
}