当前位置: 首页 > news >正文

【题解】洛谷 P2218 [HAOI2007] 覆盖问题 [二分 + 思维]

P2218 [HAOI2007] 覆盖问题 - 洛谷

答案具有单调性,可以二分。

注意到最优解的塑料膜的边上都应该有点(角上的算两条边的),即:

最上、最下、最左和最右的点,都要刚好被小正方形覆盖。

把整体的点看作一个大长方形,肯定要有一个小正方形覆盖大长方形的一个角。

(覆盖最上和最左,或最上和最右,或最下和最右,或最下和最左)

反证:如果所有小正方形都不覆盖角,那么这个大长方形肯定可以再小。

那么递归三个小正方形,每个小正方形都覆盖当前未覆盖值域的一个角。

c 是数据范围,详细时间复杂度 O((log\,c)*16*n),可以通过。

 

详细见注释代码:

#include<bits/stdc++.h>
using namespace std;typedef long long LL;
const int N = 2e4 + 10;
const LL inf = 2000000010LL;   // 极限( 1e9+10 不够大,因为坐标差可达 2e9)struct Point {LL x, y;
} a[N];int n;
int v[N];  // 标记每个点是否被覆盖(0=未覆盖)bool dfs(LL k, int id) {if (id == 4) {     // 三个小正方形全部完成 for (int i = 1; i <= n; i ++) {if (!v[i]) {return 0;}}return 1;}LL mnx = inf, mxx = -inf;LL mny = inf, mxy = -inf;for (int i = 1; i <= n; i ++) if (!v[i]) {mnx = min(mnx, a[i].x);mxx = max(mxx, a[i].x);mny = min(mny, a[i].y);mxy = max(mxy, a[i].y);} if (mnx == inf) {    // 全都覆盖了 return 1;}// 把紧贴着四个角的小正方形放进去 // 每个正方形用 pair<Point, Point> 表示:first 是左下角,second 是右上角vector<pair<Point, Point>> conner;conner.push_back({{mnx, mny}, {mnx + k, mny + k}});     // 左下角对齐conner.push_back({{mnx, mxy - k}, {mnx + k, mxy}});     // 左上角对齐conner.push_back({{mxx - k, mny}, {mxx, mny + k}});     // 右下角对齐conner.push_back({{mxx - k, mxy - k}, {mxx, mxy}});     // 右上角对齐bool flag = 0;   // 当前循环是否有解 for (auto i : conner) {LL lx = i.first.x, rx = i.second.x;LL ly = i.first.y, ry = i.second.y;// 保存当前状态,用于回溯vector<int> bak(v + 1, v + n + 1);for (int j = 1; j <= n; j ++) if (!v[j]) {if (a[j].x >= lx && a[j].x <= rx && a[j].y >= ly && a[j].y <= ry) { v[j] = id;    // 在范围内就可以覆盖到 }}flag |= dfs(k, id + 1);    // 遍历下一个小正方形 // 回溯:恢复 v 数组for (int j = 1; j <= n; j++) {v[j] = bak[j - 1];}if (flag) {break; // 提前终止(可选优化)}}return flag;
}bool check(LL k) {     // 返回 1 是成功 memset(v, 0, sizeof(v));    // 所有点都是未覆盖状态 return dfs(k, 1);   // 递归边长与小正方形编号 
}int main () {ios::sync_with_stdio(false);cin.tie(0);cin >> n;for (int i = 1; i <= n; i ++) {cin >> a[i].x >> a[i].y;}LL l = 0, r = 2000000000LL, p = 0;     // 二分枚举小正方形边长// 边长最小可以是 0(所有点重合的情况) while (l <= r) {LL mid = (l + r) >> 1;if (check(mid)) {r = mid - 1;p = mid;}else {l = mid + 1;}} cout << p << "\n";return 0;
}
http://www.dtcms.com/a/520279.html

相关文章:

  • xss-labs pass-12
  • 企业网站建设服务电话做网站什么主题好做
  • 注册电气工程师(供配电)执业资格考试专业考试规范及设计手册(2025版)
  • 关于zwg技术的深度解析与应用前景
  • linux 什么做网站好网站优化课程培训
  • 键盘PCB为何对板厂要求更高?差异、难点及猎板解决方案解析
  • OMSDK WebView Display 接入步骤
  • 零基础新手小白快速了解掌握服务集群与自动化运维(十S四)储存服务-NFS文件储存
  • tidex-数字货币交易所
  • C#使用OpenVinoSharp+魔塔社区的读光中英文OCR ONNX模型进行文字检测(仅检测不做识别)
  • 积分商城小程序深圳seo网络优化公司
  • [Linux文件系统——Lesson17.软硬链接]
  • apr库在x86架构下交叉编译成arm64架构
  • 软件设计师-结构化分析方法-耦合
  • 响应式企业网站 下载网站制作是不是要先用ps做
  • 购买网站建设需要注意app软件开发制作公司电话
  • 【AI Agent】入门、学习、求职
  • C++中const与引用深度解析:从使用到底层原理
  • Product Hunt 每日热榜 | 2025-10-23
  • 【大话码游之 Observation 传说】上集:月光宝盒里的计数玄机
  • raid恢复之后数据库故障处理(ora-01200,ORA-26101,ORA-600)---惜分飞
  • 2025年中专机电一体化专业做什么工作?
  • JavaWeb 全栈学习路径:从工具到项目的实战蜕变指南
  • 中国工信备案查询网站做网站的软件电子
  • tailwindcss暗色主题切换
  • Classwork 5 - Check the HTML Tags
  • 15、【Ubuntu】【VSCode】VSCode 断联问题分析:UID 补充
  • 本地网站404错误德州网站怎样建设
  • 从被动防御到主动防护:雷池WAF+cpolar的安全实践
  • 网络营销咨询网站源码多平台网页制作