【becoder】3088. 机器分配
题目链接:机器分配 - 题目 - 必可
思路
算法标签:【资源分配DP】【区间DP】
这里,题目已经给出将机器作为资源,我们容易想到一种贪心的做法:
【贪心做法】
找出每个公司分配机器数量产生价值的最大值,尽量分配这个数量个机器给这个公司,如果产生冲突,则优先选择价值大的,其次是用数量少的。
这样可能会 Wrong answer。
既然贪心不行,我们就采用 DP 的做法。
我们假设当前已经考虑到 i i i 公司,我们给前 i i i 个公司分配 j j j 个机器,接下来我们就要考虑给 i i i 个公司分配 k k k 台机器,则前 i − 1 i-1 i−1 个公司分配了 j − k j-k j−k 台机器,我们就可以有前 i − 1 i-1 i−1 个公司的状态,推出当前公司的状态。由此得出状转方程:
dp[i][j] = max(dp[i][j], dp[i - 1][j - k] + a[i][k]);
其中a[i][k]
是输入的价值。
因为求的是最大值,所以初始值是 0。对于全局变量,我们不需要初始值。
答案位置即给前
n
n
n 个公司分配
m
m
m 个机器的最大值,即dp[n][m]
。
【小细节】
我们可以不给第 i i i 个公司分配机器,所以 k k k 应该从零开始,范围为 ( 0 ≤ k ≤ j ) (0\le k\le j) (0≤k≤j) 。
代码
示例代码:
#include <bits/stdc++.h>
using namespace std;
const int MAXN = 105;
int n, m;
int a[MAXN][MAXN], dp[MAXN][MAXN];
int main() {
scanf("%d %d", &m, &n);
for (int i = 1; i <= n; i++)
for (int j = 1; j <= m; j++)
scanf("%d", &a[i][j]);
for (int i = 1; i <= n; i++)
for (int j = 1; j <= m; j++)
for (int k = 0; k <= j; k++)
dp[i][j] = max(dp[i][j], dp[i - 1][j - k] + a[i][k]);
printf("%d", dp[n][m]);
return 0;
}