F. Nezzar and Nice Beatmap
题目描述
解法一
根据余弦定理,如果 (|AB|geq |AC|) 时,(ang ABC<90),也就是说从任何一个点开始,每次选离它距离最大的点作为下一个点一定可以满足要求,时间复杂度 (O(n^2))
解法二
调整法,更值得学习。
先随便找一个排列,然后调整它。从后往前考虑(从前往后也一样),如果当前三个点不成锐角,那么交换后两个点的位置就可以完成调整,因为这次调整可能影响到后面,递归的继续调整后面的点即可,影响的两个点都要递归,但是真正会进入递归的只有一个。
总结
合法解的构造可以考虑调整法,特别是小范围的限制容易满足的时候。
#include<bits/stdc++.h>
using namespace std;
# define ll long long
# define read read1<ll>()
# define Type template<typename T>
Type T read1(){
T t=0;
char k;
bool vis=0;
do (k=getchar())=='-'&&(vis=1);while('0'>k||k>'9');
while('0'<=k&&k<='9')t=(t<<3)+(t<<1)+(k^'0'),k=getchar();
return vis?-t:t;
}
# define fre(k) freopen(k".in","r",stdin);freopen(k".out","w",stdout)
# define eps 1e-7
struct A{
double x,y;
A(double _x=0,double _y=0){x=_x;y=_y;}
bool vert(const A &b){return x*b.x+y*b.y==0;}
bool obt(const A &b){return x*b.x+y*b.y<=eps;}
A operator -(const A &b){return A(x-b.x,y-b.y);}
};
pair<A,int>a[5005];
int s;
void solve(int n){
if(n+1>=s)return;
while((a[n+1].first-a[n].first).obt(a[n+1].first-a[n+2].first))
swap(a[n+1],a[n+2]),solve(n+1),solve(n+2);
}
int main(){
s=read;
for(int i=1;i<=s;++i)a[i]=make_pair(A(read,read),i);
for(int n=s-2;n;--n)
while((a[n+1].first-a[n].first).obt(a[n+1].first-a[n+2].first))
swap(a[n+1],a[n+2]),solve(n+1),solve(n+2);
for(int i=1;i<=s;++i)printf("%d ",a[i].second);
return 0;
}