【HAOI 2007 覆盖问题】 二分

版权声明:若转载请附上原博客链接,谢谢! https://blog.csdn.net/Link_Ray/article/details/89293343

题解

二分正方形面积,贪心选取最优的情况,算出所有未覆盖的点的最小的矩形。那么正方形每次覆盖一个角的情况是最优,覆盖完一个角后问题又转换成了子问题,最后只要判断是否符合3个正方形即可。
在这里插入图片描述

代码

#include <bits/stdc++.h>
using namespace std;
#define FOR0(a,b) for(int i = a; i < b; ++i)
#define FORE(a,b) for(int i = a; i <= b; ++i)
typedef long long ll;
typedef pair<int,int> pii;

int n;
const int maxn = 2e4+5;
struct Point {
	ll x, y;
	void read() {
		ll _x,_y;
		scanf("%lld%lld", &_x, &_y);
		this->x = _x; this->y = _y;
	}
}p[maxn];
bool cov[maxn];

void cover(ll x1,ll y1, ll x2, ll y2) {
	for(int i = 0; i < n; ++i) {
		if(p[i].x >= x1 && p[i].x <= x2 && p[i].y >= y1 && p[i].y <= y2)
			cov[i] = 1;
	}
}
void uncover(ll x1,ll y1, ll x2, ll y2) {
	for(int i = 0; i < n; ++i) {
		if(p[i].x >= x1 && p[i].x <= x2 && p[i].y >= y1 && p[i].y <= y2)
			cov[i] = 0;
	}
}
void f(ll& x1, ll& y1, ll& x2, ll& y2) {
	y1 = x1 = INT_MAX; y2 = x2 = INT_MIN;
	// cout << x1 <<" " << x2 << endl;
	for(int i = 0; i < n; ++i) {
		if(!cov[i]) {
			x1 = min(x1,p[i].x);
			x2 = max(x2,p[i].x);
			y1 = min(y1,p[i].y);
			y2 = max(y2,p[i].y);
		}
	}
}
bool dfs(int cnt, ll k) {
	ll x1,y1,x2,y2;
	f(x1,y1,x2,y2);
	//cout << x1 <<" " << y1 <<" " << x2 << " " << y2 << endl;
	if(x2-x1 <= k && y2- y1 <= k)
		return true;
	if(cnt == 1 )
		return false;
	bool flag = false;
	cover(x1,y1,x1+k,y1+k);
	flag |= dfs(cnt-1,k);
	uncover(x1,y1,x1+k,y1+k);
	cover(x1,y2-k,x1+k,y2);
	flag |= dfs(cnt-1,k);
	uncover(x1,y2-k,x1+k,y2);
	cover(x2-k,y2-k,x2,y2);
	flag |= dfs(cnt-1,k);
	uncover(x2-k,y2-k,x2,y2);
	cover(x2-k,y1,x2,y1+k);
	flag |= dfs(cnt-1,k);
	uncover(x2-k,y1,x2,y1+k);
	return flag;
}
int main() {
	scanf("%d", &n);
	for(int i = 0; i < n; ++i) 
		p[i].read();
	ll l = 0, r = 1e18, ans = 0;
	// cout << dfs(3,0) << endl;
	while(l <= r) {
		ll mid = (l+r)>>1;
		memset(cov, 0,sizeof cov);
		if(dfs(3,mid)) {
			r = mid-1;
			ans = mid;
		} else 
			l = mid+1;
	}
	cout << ans << endl;
	return 0;
}

猜你喜欢

转载自blog.csdn.net/Link_Ray/article/details/89293343