• 【HAOI2007】覆盖问题


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

    看到这道题,很明显地可以看出来需要二分答案
    对于平面上的一些点,如果我们只使用一个尽量小的正方形覆盖它,那么这个正方形的大小和位置都是确定的
    现在的目标就是使用三个小一点的相同的正方形替换它,并保证所有点都被覆盖
    由于正方形的边必须与坐标轴平行,故小正方形至少有一条边所在的直线和大正方形的一条边所在的直线是重合的
    那么每个小正方形至少需要贡献一条边出来,因为只有3个小正方形,故一定至少有一个小正方形是贴着角的
    于是我们可以二分边长,check的时候暴力dfs判断小正方形分别在四个角时是否可以满足条件
    dfs的时候对点进行染色,方便回复到之前的状态

    代码:

    #include<bits/stdc++.h>
    #define ll long long
    #define mid ((l+r)>>1)
    #define inf 1234567890
    using namespace std;
    
    int n;
    
    struct Object
    {
    	ll x,y;
    	int color;
    }a[20005];
    
    bool cmp(Object a,Object b)
    {
    	if(a.x==b.x) return a.y<b.y;
    	return a.x<b.x;
    }
    
    void update(ll minx,ll maxx,ll miny,ll maxy,int color)//更新这个正方形覆盖到的区域 
    {
    	for(register int i=1;i<=n;++i)
    	{
    		if(!a[i].color)
    		{
    			if((minx<=a[i].x&&a[i].x<=maxx)&&(miny<=a[i].y&&a[i].y<=maxy))
    				a[i].color=color;
    		}
    	}
    }
    
    void clear(int color)//用于撤销到dfs之前的状态 
    {
    	for(register int i=1;i<=n;++i)
    		if(a[i].color==color) a[i].color=0;
    }
    
    bool dfs(int cnt,int x)
    {
    	int minx=inf,miny=inf,maxx=-inf,maxy=-inf;
    	for(register int i=1;i<=n;++i)
    	{
    		if(!a[i].color)
    		{
    			if(a[i].x>maxx) maxx=a[i].x;
    			if(a[i].x<minx) minx=a[i].x;
    			if(a[i].y>maxy) maxy=a[i].y;
    			if(a[i].y<miny) miny=a[i].y;
    		}
    	}
    	ll lenx=maxx-minx;
    	ll leny=maxy-miny;
    	if(max(lenx,leny)<=x) return true;
    	if(cnt==3) return false;
    	
    	//枚举每一种方案是否可行 
    	
    	update(minx,minx+x,miny,miny+x,cnt);
    	if(dfs(cnt+1,x)) return true;
    	clear(cnt);
    	
    	update(minx,minx+x,maxy-x,maxy,cnt);
    	if(dfs(cnt+1,x)) return true;
    	clear(cnt);
    	
    	update(maxx-x,maxx,miny,miny+x,cnt);
    	if(dfs(cnt+1,x)) return true;
    	clear(cnt);
    	
    	update(maxx-x,maxx,maxy-x,maxy,cnt);
    	if(dfs(cnt+1,x)) return true;
    	clear(cnt);
    	
    	return false;
    }
    
    bool check(int x)//检验边长为 x 的薄膜是否符合要求 
    {
    	for(register int i=1;i<=n;++i) a[i].color=0;
    	return dfs(1,x);
    }
    
    template<class T>inline void read(T &res)
    {
    	char c;T flag=1;
    	while((c=getchar())<'0'||c>'9')if(c=='-')flag=-1;res=c-'0';
    	while((c=getchar())>='0'&&c<='9')res=res*10+c-'0';res*=flag;
    }
    
    int main()
    {
    	read(n);
    	for(register int i=1;i<=n;++i)
    	{
    		read(a[i].x);
    		read(a[i].y);
    	}
    	sort(a+1,a+n+1,cmp);
    	ll l=0,r=inf;
    	while(l<r)
    	{
    		if(check(mid)) r=mid;
    		else l=mid+1;
    	}
    	printf("%d
    ",mid);
    	return 0;
    }
    

    dfs里的变量一定要开局部!开全局的话死不瞑目啊!

  • 相关阅读:
    XXX is not in the sudoers file
    git错误“无法推送一些引用到xxx"的解决方法
    mysql开启远程访问
    ubuntu 在启动器中启动webstorm和phpstorm
    ubuntu nginx卸载和安装
    基于grunt构建的前端集成开发环境
    fullPage.js
    常见的HTTP状态码
    JS随机数
    CSS3简单的动画
  • 原文地址:https://www.cnblogs.com/tqr06/p/11593905.html
Copyright © 2020-2023  润新知