團體程序設計天梯賽 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,CA,B,C三點圍城的平面區域面積爲S=AB×AC2S=\frac{\vec{AB}\times\vec{AC}}{2},即AxByAyBxA_x*B_y-A_y*B_x
4.遍歷每一對排序後的相鄰向量,維護歷史面積最小值;
//複雜度約等於O(n2logn)O(n^2\log{n})

代碼:

#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;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章