返回顶部

覆盖问题

[HAOI2007] 覆盖问题

题目描述

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

输入格式

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

输出格式

一行,输出最小的 \(L\) 值。

样例 #1

样例输入 #1

4
0 1
0 -1
1 0
-1 0

样例输出 #1

1

提示

对于 \(100\%\) 的数据,\(-1,000,000,000 \le X_i,Y_i \le 1,000,000,000。\)

对于 \(30\%\) 的数据,\(N \le 100。\)

对于 \(50\%\) 的数据,\(N \le 2000。\)

对于 \(100\%\) 的数据,\(N \le 20000。\)

看数据范围,我们知道需要开LONGLONG
然后可以通过二分+DFS求解,当然关键就在DFS上,如果纯暴力的话
image
image
不用我多说了

这个画图可知,我们从边角开始覆盖是优于从中间开始覆盖的,从中间开始覆盖未知性太多
然后我们可以二分长度L,然后DFS,用flag数组记录\(i\)是在第几次被覆盖的
覆盖时,分4种情况
\(x_{start}=a[i].x\) | \(x_{start}=a[i].x-L\)
\(x_{end}=a[i].x+L\) | \(x_{end}=a[i].x\)
############################
\(y_{start}=a[i].y\) | \(y_{start}=a[i].y-L\)
\(y_{end}=a[i].y+L\) | \(y_{end}=a[i].y\)
然后两两组合

点击查看代码
#include <bits/stdc++.h>
#define int long long
using namespace std;
const int N = 20000+10;
int n;
struct ac
{
	int x,y;
}a[N];
bool cmp(ac a,ac b)
{
	if(a.x==b.x)return a.y>b.y;
	return a.x<b.x;
}
int flag[N];
//int stx=INT_MAX,sty=INT_MAX,enx=INT_MIN,eny=INT_MIN,ans;
int ans;
bool dfs(int L,int cnt)
{
	int stx=INT_MAX,sty=INT_MAX,enx=INT_MIN,eny=INT_MIN;	
	for(int i=1;i<=n;i++)
	{
		if(!flag[i])
		{
			stx=min(stx,a[i].x);sty=min(sty,a[i].y);
			enx=max(enx,a[i].x);eny=max(eny,a[i].y);	
		}
	}
	if(max(enx-stx,eny-sty)<=L)return true;
	else if(cnt==3)return false;
	int cal[4][4];
	cal[0][0]=stx,cal[0][1]=stx+L,cal[0][2]=sty,cal[0][3]=sty+L;
	cal[1][0]=stx,cal[1][1]=stx+L,cal[1][2]=eny-L,cal[1][3]=eny;
	cal[2][0]=enx-L,cal[2][1]=enx,cal[2][2]=sty,cal[2][3]=sty+L;
	cal[3][0]=enx-L,cal[3][1]=enx,cal[3][2]=eny-L,cal[3][3]=eny;
	for(int j=0;j<4;j++)//j要放在最外面,表示0~3种情况
	{	
		int x1=cal[j][0], x2=cal[j][1], y1=cal[j][2], y2=cal[j][3];
		for(int i=1;i<=n;i++)
		{
			if(!flag[i])
			{
				if(x1<=a[i].x&&a[i].x<=x2&&y1<=a[i].y&&a[i].y<=y2)
				{
					flag[i]=cnt;
				}
			}
		}
		if(dfs(L,cnt+1))return true;//剪枝
		for(int i=1;i<=n;i++)if(flag[i]==cnt)flag[i]=0;	//回溯时记得清空	
	}
	return false;
}
bool check(int mid)
{
	for(int i=1;i<=n;i++)flag[i]=0;
	return dfs(mid,1);
}
void fen(int l,int r)
{
	while(l<=r)
	{
		int mid=(l+r)>>1;
//		cout<<mid;
		if(check(mid))
		{	
			r=mid-1;
			ans=mid;
		}else
		{
			l=mid+1;
		}
	}
}
main()
{
	ios_base::sync_with_stdio(false);
	cin.tie(0);cout.tie(0);
	cin>>n;
	for(int i=1;i<=n;i++)
	{
		cin>>a[i].x>>a[i].y;
//		stx=min(stx,a[i].x);sty=min(sty,a[i].y);
//		enx=max(enx,a[i].x);eny=max(eny,a[i].y);
	}
//	cout<<stx<<" "<<sty<<" "<<enx<<" "<<eny<<endl;
//	sort(a+1,a+1+n,cmp);
	fen(0,2e9);
	cout<<ans;
	return 0;
}
posted @ 2024-04-01 15:58  wlesq  阅读(11)  评论(0编辑  收藏  举报