团体程序设计天梯赛 L3-021 神坛(极角排序)

题目链接:

https://pintia.cn/problem-sets/994805046380707840/problems/994805046577840128

思路:

1.一共n个点,对于每一个点我们都可以将它作为顶点,那么此点和其它n-1个点就会组成n-1个向量;
2.n-1个向量中,我们任意选取两个向量都可以满足“选取三块石头”这个条件,但是我们现在的目标是面积最小,因此我们需要对这n-1个向量进行极角排序;
(证明请参考https://blog.csdn.net/lixiangITA/article/details/88628713
3. A , B , C A,B,C A,B,C三点围城的平面区域面积为 S = A B ⃗ × A C ⃗ 2 S=\frac{\vec{AB}\times\vec{AC}}{2} S=2AB ×AC ,即 A x ∗ B y − A y ∗ B x A_x*B_y-A_y*B_x AxByAyBx
4.遍历每一对排序后的相邻向量,维护历史面积最小值;
//复杂度约等于 O ( n 2 log ⁡ n ) O(n^2\log{n}) O(n2logn)

代码:

#include<bits/stdc++.h>

using namespace std;

typedef long long ll;
const int maxn = 5005;
ll x[maxn], y[maxn], ans = LLONG_MAX;

struct vec {
    
     
	ll x, y; 
	bool operator < (const vec & a) const {
    
    
		return x * a.y > y * a.x;
	}
} v[maxn];

#define a_cross(a, b) abs(a.x * b.y - a.y * b.x)	

int main() {
    
    
#ifdef MyTest
	freopen("Sakura.txt", "r", stdin);
#endif
	int n;
	scanf("%d", &n);
	for(int i = 0; i < n; ++i) scanf("%lld %lld", &x[i], &y[i]);
	for(int i = 0; i < n; ++i) {
    
    
		int tmp = 0;
		for(int j = 0; j < n; ++j) {
    
    
			if(i != j) v[tmp++] = vec{
    
    x[j] - x[i], y[j] - y[i]};
		}
		sort(v, v + tmp);
		for(int j = 1; j < tmp; ++j) {
    
    
			ans = min(ans, a_cross(v[j - 1], v[j]));	
		}
	}
	printf("%.3f", 0.5 * ans);
	return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_45228537/article/details/104733786
今日推荐