1. 程式人生 > >暴搜 bzoj1052 覆蓋問題

暴搜 bzoj1052 覆蓋問題

問題 B: 覆蓋問題
時間限制: 1 Sec 記憶體限制: 256 MB
題目描述

Description
某人在山上種了N棵小樹苗。冬天來了,溫度急速下降,小樹苗脆弱得不堪一擊,於是樹主人想用一些塑料薄
膜把這些小樹遮蓋起來,經過一番長久的思考,他決定用3個L*L的正方形塑料薄膜將小樹遮起來。我們不妨將山建
立一個平面直角座標系,設第i棵小樹的座標為(Xi,Yi),3個L*L的正方形的邊要求平行與座標軸,一個點如果在
正方形的邊界上,也算作被覆蓋。當然,我們希望塑料薄膜面積越小越好,即求L最小值。
Input
第一行有一個正整數N,表示有多少棵樹。接下來有N行,第i+1行有2個整數Xi,Yi,表示第i棵樹的座標,保證
不會有2個樹的座標相同。
Output
一行,輸出最小的L值。
Sample Input
4
0 1
0 -1
1 0
-1 0
Sample Output
1
HINT
100%的資料,N<=20000

我們對於所有點可以搞出一個覆蓋所有點的最小矩形,那麼當前的正方形一定與其邊相連,而且一定在頂點上(不然有的點在旮旯裡覆蓋不上,一定不最優),所以列舉四個頂點,列舉三次,暴搜即可。
應該沒人想不到這是二分吧?→_→

#pragma GCC optimize("O3")
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
#define N 20005
#define inf 100000000
#define ll long long
using namespace std; int read() { int sum=0,f=1;char x=getchar(); while(x<'0'||x>'9'){if(x=='-')f=-1;x=getchar();} while(x>='0'&&x<='9'){sum=(sum<<1)+(sum<<3)+x-'0';x=getchar();} return sum*f; } struct node{ll x,y;}a[N]; int n; bool vis[N]; ll hx=inf,hd=-inf,zx=inf,zd=-inf; inline
bool cmp(node a,node b){return a.x==b.x?a.y<b.y:a.x<b.x;} inline int check(ll h1,ll h2,ll z1,ll z2,ll x,int h) { if(h==4)return 0; ll f1=inf,f2=-inf,g1=inf,g2=-inf;int hh[N];memcpy(hh,vis,sizeof(vis)); for(int i=1;i<=n;i++)if(!vis[i]&&a[i].x<=h1+x&&a[i].y<=z1+x)vis[i]=1; int s=0;for(int i=1;i<=n;i++)if(vis[i])s++;if(s==n)return 1; for(int i=1;i<=n;i++) { if(vis[i])continue; if(a[i].x>f2)f2=a[i].x; if(a[i].x<f1)f1=a[i].x; if(a[i].y>g2)g2=a[i].y; if(a[i].y<g1)g1=a[i].y; } int k=check(f1,f2,g1,g2,x,h+1);if(k==1)return 1; memcpy(vis,hh,sizeof(vis)); f1=inf,f2=-inf,g1=inf,g2=-inf;memcpy(hh,vis,sizeof(vis)); for(int i=1;i<=n;i++)if(!vis[i]&&a[i].x<=h1+x&&a[i].y>=z2-x)vis[i]=1; s=0;for(int i=1;i<=n;i++)if(vis[i])s++;if(s==n)return 1; for(int i=1;i<=n;i++) { if(vis[i])continue; if(a[i].x>f2)f2=a[i].x; if(a[i].x<f1)f1=a[i].x; if(a[i].y>g2)g2=a[i].y; if(a[i].y<g1)g1=a[i].y; } k=check(f1,f2,g1,g2,x,h+1);if(k==1)return 1; memcpy(vis,hh,sizeof(vis)); f1=inf,f2=-inf,g1=inf,g2=-inf;memcpy(hh,vis,sizeof(vis)); for(int i=1;i<=n;i++)if(!vis[i]&&a[i].x>=h2-x&&a[i].y<=z1+x)vis[i]=1; s=0;for(int i=1;i<=n;i++)if(vis[i])s++;if(s==n)return 1; for(int i=1;i<=n;i++) { if(vis[i])continue; if(a[i].x>f2)f2=a[i].x; if(a[i].x<f1)f1=a[i].x; if(a[i].y>g2)g2=a[i].y; if(a[i].y<g1)g1=a[i].y; } k=check(f1,f2,g1,g2,x,h+1);if(k==1)return 1; memcpy(vis,hh,sizeof(vis)); f1=inf,f2=-inf,g1=inf,g2=-inf;memcpy(hh,vis,sizeof(vis)); for(int i=1;i<=n;i++)if(!vis[i]&&a[i].x>=h2-x&&a[i].y>=z2-x)vis[i]=1; s=0;for(int i=1;i<=n;i++)if(vis[i])s++;if(s==n)return 1; for(int i=1;i<=n;i++) { if(vis[i])continue; if(a[i].x>f2)f2=a[i].x; if(a[i].x<f1)f1=a[i].x; if(a[i].y>g2)g2=a[i].y; if(a[i].y<g1)g1=a[i].y; } k=check(f1,f2,g1,g2,x,h+1);if(k==1)return 1; memcpy(vis,hh,sizeof(vis)); return 0; } int main() { n=read();ll x,y;if(n==0){cout<<0;return 0;} for(int i=1;i<=n;i++)a[i].x=read(),a[i].y=read(); sort(a+1,a+n+1,cmp); for(int i=1;i<=n;i++) { if(a[i].x>hd)hd=a[i].x; if(a[i].x<hx)hx=a[i].x; if(a[i].y>zd)zd=a[i].y; if(a[i].y<zx)zx=a[i].y; } ll l=0,r=max(zd-zx,hd-hx),mid,ans; while(l<=r) { mid=(l+r)/2; memset(vis,0,sizeof(vis)); if(check(hx,hd,zx,zd,mid,1))ans=mid,r=mid-1; else l=mid+1; } cout<<ans; }