首页 > 其他分享 >[HAOI2007][洛谷P2218]覆盖问题

[HAOI2007][洛谷P2218]覆盖问题

时间:2024-03-20 11:33:06浏览次数:29  
标签:二分 const int HAOI2007 正方形 ans 洛谷 P2218 矩形

image

看到这道题,思考一下后发现要用二分答案。所以为什么要用二分?
因为标签有二分还在二分专题里
因为对于 \(ans\) 来说,如果 \(ans\) 不行,那么 \(ans-1\) 也一定不行;也就是说,答案满足单调性,所以可以二分;
也是因为暴力明显过不了

那么对于平面上的一些点来说,如果我们用一个最小的矩形覆盖所有点,那么这个矩形的大小和位置都是固定的;

所以我们的目标就是三个等大的小正方形替换它,并保证所有点仍被覆盖;

由于小正方形的边与坐标轴平行,而这个最小的矩形的每个边上都至少有一个点(否则不满足“最小”),所以每个小正方形一定至少有一条边与大长方形重合;

而由于我们只有三个正方形,所以一定有一个正方形在角上;

到这里,思路已经很清晰了:
二分小正方形边长,dfs 四个角的四种情况,得出答案

完整代码
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=2e4+5;
const int inf=0x7fffffff;
struct tree{
	int x,y,now;
	bool operator < (const tree &a)const{//优先按照 x 升序,x 相等按 y 升序 
		if(x==a.x)return y<a.y;
		return x<a.x;
	}
}a[N];
int n,maxn;
void cap(int minx,int maxx,int miny,int maxy,int now){//对指定区间进行覆盖,now记录当前是第几块塑料布 
	for(int i=1;i<=n;i++){
		if(a[i].now)continue;
		if(minx<=a[i].x&&a[i].x<=maxx&&miny<=a[i].y&&a[i].y<=maxy)
			a[i].now=now;
	}
}
void recap(int now){//取消点当前的now标记 (之前的不会清空) 
	for(int i=1;i<=n;i++){
		if(a[i].now==now)a[i].now=0;
	}
}
bool dfs(int now,int mid){
	int minx=inf,maxx=-inf;
	int miny=inf,maxy=-inf;
	for(int i=1;i<=n;i++){
		if(!a[i].now){//在未被覆盖的点中寻找最大与最小 x y 坐标 
			maxx=max(maxx,a[i].x); 
			minx=min(minx,a[i].x);
			maxy=max(maxy,a[i].y);
			miny=min(miny,a[i].y);
		}
	}
	int lenx=maxx-minx;
	int leny=maxy-miny;
	if(max(lenx,leny)<=mid)return 1;//能够覆盖 
	if(now==3)return 0;//塑料布用完了 
	
	cap(minx,minx+mid,miny,miny+mid,now);//左下角 
	if(dfs(now+1,mid))return 1;//寻找下一块 
	recap(now);//回溯 
	
	cap(minx,minx+mid,maxy-mid,maxy,now);//左上角 
	if(dfs(now+1,mid))return 1;
	recap(now);
	
	cap(maxx-mid,maxx,miny,miny+mid,now);//右下角 
	if(dfs(now+1,mid))return 1;
	recap(now);
	
	cap(maxx-mid,maxx,maxy-mid,maxy,now);//右上角 
	if(dfs(now+1,mid))return 1;
	recap(now);
	
	return 0;
}
bool check(int x){
	for(int i=1;i<=n;i++)a[i].now=0;//清空覆盖状态 
	return dfs(1,x);//dfs 
}
int solve(int l,int r){//喜欢打递归版的二分答案 
	int mid=(l+r)>>1;
	if(r<=l)return mid;
	if(check(mid))return solve(l,mid);
	else return solve(mid+1,r);
}
int main(){
	cin>>n;
	for(int i=1;i<=n;i++){
		cin>>a[i].x>>a[i].y;
	}
	sort(a+1,a+1+n);//记得排序 
	cout<<solve(1,inf);
	return 0;
}

标签:二分,const,int,HAOI2007,正方形,ans,洛谷,P2218,矩形
From: https://www.cnblogs.com/LBTL/p/18084883

相关文章

  • [NOI2010][洛谷P2048]超级钢琴
    一道很不错也很难的ST表Debug了好久之后发现撞变量了......
  • 蓝桥杯 2013 国 AC 网络寻路 第四届国赛 洛谷P8605
    [蓝桥杯2013国AC]网络寻路题目描述XXX国的一个网络使用若干条线路连接若干个节点。节点间的通信是双向的。某重要数据包,为了安全起见,必须恰好被转发两次到达目的地。该包可能在任意一个节点产生,我们需要知道该网络中一共有多少种不同的转发路径。源地址和目标地......
  • [SCOI2011][洛谷P3275] 糖果
    本来这是一道差分约束板子题/水题SPFA-BFS和SPFA-DFS都能过BFS#include<bits/stdc++.h>usingnamespacestd;typedeflonglongll;constllN=100005;#definemax(a,b)((a)>(b)?(a):(b))#definemin(a,b)((a)<(b)?(a):(b))structedge{ intto,next,w;}e[N*1000]......
  • 洛谷 P2934 [USACO09JAN] Safe Travel G 题解
    前话貌似别人都是使用并查集维护的方法,然而由于排序、最短路等算法瓶颈,以下令\(n\)和\(m\)同阶,总的时间复杂度依然是\(\Theta(n\logn)\)的,那么并查集是否有点大材小用了。事实上,在建完最短路径树后,我给出了两种带\(\log\)的数据结构完成此题。题目分析翻译里已经把问......
  • 洛谷题单指南-二叉树-P1185 绘制二叉树
    原题链接:https://www.luogu.com.cn/problem/P1185题意解读:在表格中绘制二叉树,有几个关键点1、结点用小写字母o 表示,对于一个父亲结点,用 / 连接左子树,用 \连接右子树,表格其余地方填空格。2、第m层结点若两个属于同一个父亲,那么它们之间由 3个空格隔开;若两个结点相邻但......
  • 洛谷-P1449 后缀表达式
    目录 何为后缀表达式?模拟过程AC代码采用STL的stack题目链接:P1449后缀表达式-洛谷|计算机科学教育新生态(luogu.com.cn) 何为后缀表达式?那后缀表达式是怎么算的呢那显然就需要引用最开始说的栈了因为后缀表表达式本来就是栈的一种应用那么现在来说说后缀表......
  • 洛谷题单指南-二叉树-P3884 [JLOI2009] 二叉树问题
    原题链接:https://www.luogu.com.cn/problem/P3884题意解读:要计算二叉树的深度、宽度、节点间的距离,深度、宽度的概念很好理解,节点间的距离描述是:节点u,v之间的距离表示从u到v的最短有向路径上向根节点的边数的两倍加上向叶节点的边数。说人话就是:u到v的距离=uv最近公共祖先到u......
  • 洛谷——P1152欢乐的跳
      思路1、接收数据2、abs得出相邻两数差的绝对值,存入数组3、用f=true,记录是否满足条件4、对数组进行排序后,判断是否等于[1,n-1]间的数,有一个不是就跳出循环 importjava.util.Arrays;importjava.util.Scanner;publicclassMain{publicstaticvoidmain(St......
  • 每日一题 第三期 洛谷 国王游戏
    [NOIP2012提高组]国王游戏题目描述恰逢H国国庆,国王邀请nnn位大臣来玩一个有奖游戏。首先,他让每个大臣在左、右手上面分别写下一个整数,国王自己也在左、右手上各写......
  • 【洛谷 P8661】[蓝桥杯 2018 省 B] 日志统计 题解(滑动窗口+优先队列+双端队列+集合)
    [蓝桥杯2018省B]日志统计题目描述小明维护着一个程序员论坛。现在他收集了一份“点赞”日志,日志共有NNN行。其中每一行的格式是tsid,表示在......