覆盖问题 bzoj1052

题目来源:HAOI 2007

题目描述

某人在山上种了N棵小树苗。冬天来了,温度急速下降,小树苗脆弱得不堪一击,于是树主人想用一些塑料薄膜把这些小树遮盖起来,经过一番长久的思考,他决定用3个L*L的正方形塑料薄膜将小树遮起来。我们不妨将山建立一个平面直角坐标系,设第i棵小树的坐标为(Xi,Yi),3个L*L的正方形的边要求平行与坐标轴,一个点如果在正方形的边界上,也算作被覆盖。当然,我们希望塑料薄膜面积越小越好,即求L最小值。

输入输出

input

第一行有一个正整数N,表示有多少棵树。

接下来有N行,第i+1行有2个整数Xi,Yi,表示第i棵树的坐标,保证不会有2个树的坐标相同。

output

一行,输出最小的L值

样例

input

4
0 1
0 -1
1 0
-1 0

output

1 

数据范围

100%的数据,N<=20000

思路

确定在一定范围内有一些点,然后用边长为常数k(<边界范围)的三个正方形去覆盖它们的话,如果有合法的方案,那么一定存在至少一个正方形,它的两条边分别卡在两个边界上。 
这个性质非常容易证明。因为如果确定是上下左右的边界,那么每一个边界上至少有一个点需要去覆盖。然而我们只有三个正方形,若想要覆盖这四个点,一定存在一个正方形覆盖了两个点,那么它就一定卡在两个边界上。如果正方形数少的话就更显然了。 
做法:二分出一个答案k,然后dfs判断。dfs每一次放一个正方形,枚举它卡着当前区域的哪两个边界即可。

代码

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <algorithm>
#include <cstring> #define N 22222
#define INF 2147483647 using namespace std;
/*
首先,求出所有点的4个边界值形成的一个矩形,第一个正方形的一个边界一定与这个矩形的4个角中的一个重合,枚举4次即可,
然后再找到剩下的点中的边界,重复一遍上面的操作,最后判断一下一个正方形是否可以覆盖剩余的所有矩形
*/
struct P
{
int x,y;
}p[N],p1[N],p2[N]; int n; inline void read()
{
scanf("%d",&n);
for(int i=1;i<=n;i++) scanf("%d%d",&p[i].x,&p[i].y);
} inline bool check(int len)
{
if(n==0) return true;
int sd[4][4];
sd[1][1]=INF; sd[1][2]=-INF;
sd[2][1]=INF; sd[2][2]=-INF;
for(int i=1;i<=n;i++)
{
sd[1][1]=min(sd[1][1],p[i].x); sd[1][2]=max(sd[1][2],p[i].x);
sd[2][1]=min(sd[2][1],p[i].y); sd[2][2]=max(sd[2][2],p[i].y);
}
for(int i=1;i<=2;i++)
for(int j=1;j<=2;j++)
{
int m=0;
for(int k=1;k<=n;k++)
if(abs(p[k].x-sd[1][i])>len||abs(p[k].y-sd[2][j])>len) p1[++m]=p[k];
if(m==0) return true; int sp[4][4];
sp[1][1]=INF; sp[1][2]=-INF;
sp[2][1]=INF; sp[2][2]=-INF;
for(int k=1;k<=m;k++)
{
sp[1][1]=min(sp[1][1],p1[k].x); sp[1][2]=max(sp[1][2],p1[k].x);
sp[2][1]=min(sp[2][1],p1[k].y); sp[2][2]=max(sp[2][2],p1[k].y);
}
for(int ii=1;ii<=2;ii++)
for(int jj=1;jj<=2;jj++)
{
int s=0;
for(int kk=1;kk<=m;kk++)
if(abs(p1[kk].x-sp[1][ii])>len||abs(p1[kk].y-sp[2][jj])>len) p2[++s]=p1[kk];
if(s==0) return true; int sq[4][4];
sq[1][1]=INF; sq[1][2]=-INF;
sq[2][1]=INF; sq[2][2]=-INF;
for(int kk=1;kk<=s;kk++)
{
sq[1][1]=min(sq[1][1],p2[kk].x); sq[1][2]=max(sq[1][2],p2[kk].x);
sq[2][1]=min(sq[2][1],p2[kk].y); sq[2][2]=max(sq[2][2],p2[kk].y);
}
if(sq[2][2]-sq[2][1]<=len&&sq[1][2]-sq[1][1]<=len) return true;
}
}
return false;
} inline void go()
{
int l=0,r=2000000000,mid,ans;
while(l<=r)
{
mid=(l+r)>>1;
if(check(mid)) ans=mid,r=mid-1;
else l=mid+1;
}
printf("%d\n",ans);
} int main()
{
read(),go();
return 0;
}

参考:http://www.cnblogs.com/proverbs/archive/2013/03/12/2956827.html

【二分 贪心】覆盖问题 BZOJ1052 HAOI2007的更多相关文章

  1. 【题解】覆盖问题 BZOJ1052 HAOI2007 二分

    题目描述 某 人在山上种了N棵小树苗.冬天来了,温度急速下降,小树苗脆弱得不堪一击,于是树主人想用一些塑料薄膜把这些小树遮盖起来,经过一番长久的思考,他决定用 3个LL的正方形塑料薄膜将小树遮起来.我 ...

  2. $bzoj2067\ szn$ 二分+贪心

    正解:二分+贪心 解题报告: 传送门$QwQ$ 题目大意就说有一棵树,然后要用若干条线覆盖所有边且不能重叠.问最少要用几条线,在用线最少的前提下最长的线最短是多长. 昂首先最少用多少条线这个还是蛮$e ...

  3. Codeforces Gym 100231B Intervals 线段树+二分+贪心

    Intervals 题目连接: http://codeforces.com/gym/100231/attachments Description 给你n个区间,告诉你每个区间内都有ci个数 然后你需要 ...

  4. 2016-2017 ACM-ICPC CHINA-Final Ice Cream Tower 二分+贪心

    /** 题目:2016-2017 ACM-ICPC CHINA-Final Ice Cream Tower 链接:http://codeforces.com/gym/101194 题意:给n个木块,堆 ...

  5. 【bzoj2097】[Usaco2010 Dec]Exercise 奶牛健美操 二分+贪心

    题目描述 Farmer John为了保持奶牛们的健康,让可怜的奶牛们不停在牧场之间 的小路上奔跑.这些奶牛的路径集合可以被表示成一个点集和一些连接 两个顶点的双向路,使得每对点之间恰好有一条简单路径. ...

  6. Codeforces_732D_(二分贪心)

    D. Exams time limit per test 1 second memory limit per test 256 megabytes input standard input outpu ...

  7. CF732D Exams 二分 贪心

    思路:二分+贪心 提交次数:10次以上 错因:刚开始以为二分(边界,$+1or-1$)写错了,调了半天,后来才发现是$ck()$写错了.开始只判了最后是否小于零,而应该中间一旦小于零就$return\ ...

  8. 二分判定 覆盖问题 BZOJ 1052

    //二分判定 覆盖问题 BZOJ 1052 // 首先确定一个最小矩阵包围所有点,则最优正方形的一个角一定与矩形一个角重合. // 然后枚举每个角,再解决子问题 #include <bits/s ...

  9. $CF949D\ Curfew$ 二分/贪心

    正解:二分/贪心 解题报告: 传送门$QwQ$ 首先这里是二分还是蛮显然的?考虑二分那个最大值,然后先保证一个老师是合法的再看另一个老师那里是否合法就成$QwQ$. 发现不太会搞这个合不合法的所以咕了 ...

随机推荐

  1. 【转】python SQLAlchemy

    数据库表是一个二维表,包含多行多列. 把一个表的内容用Python的数据结构表示出来的话,可以用一个list表示多行,list的每一个元素是tuple,表示一行记录,比如,包含id和name的user ...

  2. SQL必知必会 —— 性能优化篇

    数据库调优概述 数据库中的存储结构是怎样的 在数据库中,不论读一行,还是读多行,都是将这些行所在的页进行加载.也就是说,数据库管理存储空间的基本单位是页(Page). 一个页中可以存储多个行记录(Ro ...

  3. 手把手教你看MySQL官方文档

    前言: 在学习和使用MySQL的过程中,难免会遇到各种问题.不知道当你遇到相关问题时会怎么做,我在工作或写文章的过程中,遇到不懂或需要求证的问题时通常会去查阅官方文档.慢慢的,阅读文档也有了一些经验, ...

  4. (转)通过gitlab统计git提交的代码量

    git的代码量大多数都是根据命令行统计,或者根据第三方插件统计.但是都不满足我的需求,因为我们代码都由gitlab管理,于是想到了通过gitlab暴露出来的接口获取数据. 第一步,生成私钥 登录你的g ...

  5. mitrproxy抓包微信小程序

    mitmproxy mitmproxy is a set of tools that provide an interactive, SSL/TLS-capable intercepting prox ...

  6. 登录框-element-ui 样式调节

    element-ui样式调节 首先设置布局 如果想要实现如下效果 需要两行,然后设置偏移,第一行中间只是站位,没有内容,可以考虑使用div占位,设置最小高度 el-card调整圆角 border-ra ...

  7. Python菜鸟100例

    题目地址 #-*- codeing = utf-8 -*- #@Time : 2021/3/18 21:17 #@Author : HUGBOY #@File : 1.py #@Software: P ...

  8. IT菜鸟之虚拟机VMware的安装

    老师说过,如果想学好Linux,最好不要在实体机上安装Linux,因为学习需要经常折腾,在实体机上做实验,出现故障就要重新安装,这样绝大多数时间都会浪费在安装上. 这时我们需要一个工具,它就是虚拟机. ...

  9. MyBatis 模糊查询的 4 种实现方式

    引言 MyBatis 有 4 种方式可以实现模糊查询. 员工信息表 ( tb_employee ) 如下: id name sex email birthday address 001 张一凡 男 z ...

  10. MyBatis 高级查询之一对多查询(十)

    高级查询之一对多查询 查询条件:根据游戏名称,查询游戏账号信息 我们在之前创建的映射器接口 GameMapper.java 中添加接口方法,如下: /** * 根据游戏名查询游戏账号 * @param ...