1. 程式人生 > 其它 >codeforces1478F Nezzar and Nice Beatmap

codeforces1478F Nezzar and Nice Beatmap

技術標籤:計算幾何

題目:

在平面上按序給定 n n n個點,問能不能將這些點重新排序,使任意三個相鄰的點形成的角都是銳角,若能就輸出新的序列,不能輸出-1。
( 3 ≤ n ≤ 5000 ) (3 \le n \le 5000) (3n5000)

題解:

法1: 先隨便找一個點確定為第一個點,然後每次在剩下的點集中找與之前確定的最後一個點距離最遠的點。假設之前兩次的點分別為 A , B A,B A,B,這次確定的點是 C C C,顯然 A B ≥ A C AB \ge AC ABAC,由大邊對大角可知 ∠ A B C ≤ ∠ A C B \angle ABC \le \angle ACB A

BCACB,所以 ∠ A B C \angle ABC ABC一定是銳角。但是這個演算法的複雜度為 O ( n 2 l o g n ) O(n^2logn) O(n2logn),通不過這道題。
法2: 在一個三角形中,鈍角或直角只能有一個,所以當三個相鄰的點 A i , A i + 1 , A i + 2 A_i,A_{i+1},A_{i+2} Ai,Ai+1,Ai+2形成一個非銳角 ∠ A i A i + 1 A i + 2 \angle A_iA_{i+1}A_{i+2} AiAi+1Ai+2時,交換 A i + 1 A_{i+1} Ai+1 A i + 2 A_{i+2}
Ai+2
即可使這三個點形成的角為銳角。所以我們遍歷所有的點,每次將字首調整到滿足要求即可。
卡了精度,不要使用 d o u b l e double double,用 i n t int int實現。

複雜度: O ( n 2 ) O(n^2) O(n2)

程式碼:

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<vector>
#include<queue>
#include
<stack>
#include<map> #include<set> #include<string> #include<bitset> #include<sstream> #include<ctime> //#include<chrono> //#include<random> //#include<unordered_map> using namespace std; #define ll long long #define ls o<<1 #define rs o<<1|1 #define pii pair<int,int> #define fi first #define se second #define pb push_back #define mp make_pair #define sz(x) (int)(x).size() #define all(x) (x).begin(),(x).end() const double pi=acos(-1.0); const double eps=1e-9; const int mod=1e9+7; const int INF=0x3f3f3f3f; const int maxn=5005; ll read(){ ll x=0,f=1; char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();} return x*f; } int n; struct Point{ int x,y,id; Point(int x=0,int y=0):x(x),y(y){} }; Point p[maxn]; Point operator-(Point a,Point b){ return Point(a.x-b.x,a.y-b.y); } ll Dot(Point a,Point b){ return 1ll*a.x*b.x+1ll*a.y*b.y; } int main(void){ // freopen("in.txt","r",stdin); scanf("%d",&n); for(int i=1;i<=n;i++){ scanf("%d%d",&p[i].x,&p[i].y); p[i].id=i; } for(int i=3;i<=n;i++){ for(int j=i;j>=3;j--){ if(Dot(p[j]-p[j-1],p[j-2]-p[j-1])<=0){ swap(p[j],p[j-1]); } else break; } } for(int i=1;i<=n;i++){ printf("%d ",p[i].id); } puts(""); return 0; }