AcWing 1013. 机器分配 (分组背包)

简介: 笔记

1013. 机器分配


题意

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


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


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


求出最大盈利值。


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


思路

分组背包裸题

状态表示f[i][j] 表示分配到前 i个公司 已经分配了j 台机器的利润最大值

状态计算:

设 k 表示给当前公司分配 k台机器

则k∈[1,j]

不给当前公司分配机器:f[i][j]=f[i−1][j]

给当前公司分配 k kk 台机器: f[i][j]=f[i−1][j−k]+w[i][k]

最后取max 即可

注意:需要输出具体方案 所以我们求f[i][j] 时从后往前求 这样的到的方案字典序最小


代码

#include<bits/stdc++.h>
#define INF 0x3f3f3f3f
#define mod 998244353
#define endl '\n'
#define int long long
using namespace std;
inline int gcd(int a, int b) { return b ? gcd(b, a%b) : a; }
inline int lowbit(int x) { return x & -x; }
typedef long long LL;
typedef pair<int, int>PII;
const int N = 1010;
int n, m;
int w[N][N];
int f[N][N];
int res[N];
void solve() {
  cin >> n >> m;
  for (int i = 1; i <= n; ++i) {
    for (int j = 1; j <= m; ++j) {
      scanf("%lld", &w[i][j]);
    }
  }
  //前 i 个公司 分配 j 个机器的 利润最大值
  for (int i = n; i >= 1; --i) {
    for (int j = 1; j <= m; ++j) {
      f[i][j] = f[i + 1][j];
      for (int k = 1; k <= m; ++k) {
        if (j - k >= 0)
          f[i][j] = max(f[i][j], f[i + 1][j - k] + w[i][k]);
      }
    }
  }
  cout << f[1][m] << endl;
  int ans = m;
  for (int i = 1; i <= n; ++i) {
    for (int k = 1; k <= m; ++k) {
      if (ans >= k && f[i][ans] == f[i + 1][ans - k] + w[i][k]) {
        res[i] = k;
        ans -= k;
        break;
      }
    }
  }
  for (int i = 1; i <= n; ++i)
    printf("%lld %lld\n", i, res[i]);
}
signed main() {
  //int t; cin >> t;
  //while(t--)
  solve();
  return 0;
}


目录
相关文章
|
8月前
|
测试技术
力扣888 公平糖果交换
力扣888 公平糖果交换
|
8月前
【每日一题Day168】LC2427公因子的数目 | 模拟
【每日一题Day168】LC2427公因子的数目 | 模拟
48 1
|
7月前
每日一题 1020. 飞地的数量
每日一题 1020. 飞地的数量
|
7月前
|
机器学习/深度学习 人工智能
【洛谷 P1028】[NOIP2001 普及组] 数的计算 题解(递推)
在NOIP2001普及组的数的计算题目中,给定自然数`n`,需构造遵循特定规则的合法数列。合法序列始于`n`,新元素不超过前一项的一半。任务是找出所有这样的数列数量。例如,当`n=6`时,合法序列包括`6`, `6,1`, `6,2`, `6,3`, `6,2,1`, `6,3,1`。程序通过动态规划求解,当`i`为奇数时,`a[i] = a[i - 1]`;为偶数时,`a[i] = a[i - 1] + a[i / 2]`。代码中预处理数组`a`并输出`a[n]`作为答案。输入`n`后,程序直接计算并打印合法数列个数。
81 0
|
7月前
|
机器学习/深度学习 存储
【洛谷 P1028】[NOIP2001 普及组] 数的计算 题解(递归)
**NOIP2001普及组数的计算**:给定自然数\( n \),构造数列,新数不超过序列最后一项一半。求合法数列个数。输入\( n \)(\(1 \leq n \leq 10^3\))。样例:输入6,输出6。递归解决,代码中定义函数`f`实现递归计算,总和存储在`cnt`中,最后输出。
64 0
|
8月前
|
人工智能
888. 公平的糖果棒交换(力扣)
888. 公平的糖果棒交换(力扣)
|
8月前
|
存储
糖果分配方案
糖果分配方案
99 0
|
8月前
|
算法 Java C++
买不到的数目
买不到的数目
44 0
|
算法
【算法挨揍日记】day06——1004. 最大连续1的个数 III、1658. 将 x 减到 0 的最小操作数
1004. 最大连续1的个数 III 题目描述: 给定一个二进制数组 nums 和一个整数 k,如果可以翻转最多 k 个 0 ,则返回 数组中连续 1 的最大个数 。
417 1
|
算法 C语言 C++
LeetCode.每日一题 2427. 公因子的数目
将一个数的所有约数枚举出来,存入数组,之后再用数组中的每一个数,去看看能不能被第二个数整除,若能则答案++
65 0

热门文章

最新文章