Codeforces Round #698 (Div. 2)

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;
}
posted @ 2021-06-24 17:42  C202044zxy  阅读(22)  评论(0编辑  收藏  举报