CF2000F Color Rows and Columns

题目链接

题解

知识点:贪心、背包dp。

先考虑一个矩形的情况:

  1. 若是方形,行列交替染色最优。
  2. 若不是方形,选行列中较小的一侧染色,直到变为方形。

因此,我们可以根据上面的结论预处理 ci,j ,表示第 i 个矩形贡献为 j 的最小花费。

现在考虑多个矩形的情况,显然是一个分组背包问题。每个矩形为一个组,第 i 个矩形有 ai+bi+1 个项(包括不选) ,第 j 项贡献为 j 花费是 ci,j ,每组只能选一个。

我们设 fi,j 表示前 i 个矩形贡献为 j 时的最小花费。特别地,根据题意我们采用一个技巧,定义 fi,k 表示前 i 个矩形贡献至少为 k 时的最小花费。

计算花费有两种方法,打表法和刷表法,前者寻找前导状态更新当前状态,后者寻找后继状态更新后继状态,采用上述技巧后更适合采用刷表法。打表法实现和效率都会更复杂,因为 fi,k 的前导状态将变为 wi,j=j=0ai+bij ,而非 j 个。

初始化正无穷,f0,0=0 ,转移方程如下:

for (int i = 1;i <= n;i++) {
for (int j = 0;j <= k;j++) {
for (int id = 0;id <= a[i] + b[i];id++) {
f[i][min(k, j + id)] = min(f[i][min(k, j + id)], f[i - 1][j] + c[i][id]);
}
}
}

此外,如果采用单行滚动数组优化,第二层循环应变为逆序,且第二层和第三层循环不能交换。

当然,也可以采用两行数组实现滚动数组,更方便。

时间复杂度 O(nkmax{ai,bi})

空间复杂度 O(n(k+max{ai,bi}))

代码

#include <bits/stdc++.h>
using namespace std;
using ll = long long;
int a[1007], b[1007];
int c[1007][207]; // 第 i 个矩形贡献为 j 的最小花费
int f[1007][107]; // 前 i 个矩形贡献为 j 的最小花费,分组背包
bool solve() {
int n, k;
cin >> n >> k;
for (int i = 1;i <= n;i++) {
cin >> a[i] >> b[i];
int delta = abs(a[i] - b[i]);
// 短边先填,直至方形
for (int j = 1;j <= delta;j++) c[i][j] = c[i][j - 1] + min(a[i], b[i]);
// 方形行列交替填
for (int j = delta + 1; j <= a[i] + b[i];j++) c[i][j] = c[i][j - 1] + min(a[i], b[i]) - (j - delta) / 2;
}
for (int i = 0;i <= n;i++)
for (int j = 0;j <= k;j++)
f[i][j] = 1e9;
// 建议刷表法,因为 fi,k 表示前 i 个矩形贡献 >= k 的最小花费,填表法在 fi,k 的处理会更复杂,效率也更低
f[0][0] = 0;
for (int i = 1;i <= n;i++) {
for (int j = 0;j <= k;j++) {
for (int id = 0;id <= a[i] + b[i];id++) {
f[i][min(k, j + id)] = min(f[i][min(k, j + id)], f[i - 1][j] + c[i][id]);
}
}
}
cout << (f[n][k] > 1e8 ? -1 : f[n][k]) << '\n';
return true;
}
int main() {
std::ios::sync_with_stdio(0), std::cin.tie(0), std::cout.tie(0);
int t = 1;
cin >> t;
while (t--) {
if (!solve()) cout << -1 << '\n';
}
return 0;
}
posted @   空白菌  阅读(10)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
点击右上角即可分享
微信分享提示