HDU4353 Finding Mine

微微发亮的传送门

去年某一场多校联合赛的题,题意就是给了N个黑点,M个红点,用黑点围成一个多边形,使得它的面积比上它里面的红点的比值最小。

乍一看,好屌的样子,但是实际上我们想一想,假设我们找到了这么一个多边形,而且是边数大于3的,那么这个多边形肯定能分成好几个三角形,这些三角形面积和红点个数的比值有可能是一样的,一样的话,求出来这个三角形和费大劲儿求出来多边形是完全一样的,那么我们只需要考虑比值不同的情况。

如果比值不同,那么一定是有大有小,那么试想一下,一个比值最小的三角形,合一个比值比它大的三角形形成一个多边形,不管凸的凹的的话,那么最终组成的这个多边形比值肯定比那个三角形大啊,既然这样,就得到了一个结论,我们得到的一定是一个三角形,如果是这样的话,下面就好说了。

首先,我们可以通过叉积预处理出来每一个线段的Y方向上方有多少个红点,这个复杂度是O(N^2*M)的,然后对于一个三角形,一条边正上方的点减去另外两条边正上方的点就是三角形中的点,这样每个三角形我们可以O(1)求出来里面有多少个红点。最后三角形我们完全可以排序之后暴力查找,整道题的复杂度是O(NlogN+N^2*M+N^3)的,以这道题的数据量来讲,完全可以接受。

#include 
#include 
#include 
#include 
#include 
using namespace std;
struct point{
	int x, y;
	point() {}
	point(int a, int b) : x(a), y(b){}
	void input(){
		scanf("%d%d", &x, &y);
	}
	friend point operator - (const point &a, const point &b){
		return point(a.x - b.x, a.y - b.y);
	}
	friend bool operator < (const point &a, const point &b){
		return a.x < b.x;
	}
};
const int maxn = 200 + 10, maxm = 500 + 10;
point po[maxn], mi[maxm];
int det(point a, point b){
	return a.x * b.y - a.y * b.x;
}
int num[maxn][maxn];
int n, m, cs;
void init(point a, point b, int &cnt){
	int x1 = a.x, x2 = b.x;
	for (int i = 0; i < m; i++)
		if (mi[i].x >= x1 && mi[i].x < x2)
			if (det(mi[i] - a, b - a) > 0)
				cnt += 1;
}
int main(){
	#ifndef ONLINE_JUDGE
	freopen("in", "rt", stdin);
	#endif
	scanf("%d", &cs);
	for (int kase = 1; kase <= cs; ++kase){
		scanf("%d%d", &n, &m);
		for (int i = 0; i < n; i++)
			po[i].input();
		for (int i = 0; i < m; i++)
			mi[i].input();
		sort(po, po + n);
		for (int i = 0; i < n; i++)
			for (int j = i + 1; j < n; j++)
				init(po[i], po[j], num[i][j] = 0);
		printf("Case #%d: ", kase);
		double ans = -1;
		for (int i = 0; i < n; i++)
			for (int j = i + 1; j < n; j++)
				for (int k = j + 1; k < n; k++){
					int cnt = num[i][k] - num[i][j] - num[j][k];
					if (!cnt) continue;
					double area = det(po[j] - po[i], po[k] - po[i]) / 2.0;
					double tmp = area / (double)cnt;
					if (ans == -1 || ans > tmp) ans = tmp;
				}
		if (ans == -1) puts("-1");
		else printf("%.6lf\n", ans);
	}
	return 0;
}


你可能感兴趣的:(计算几何)