P3454 OSI-Axes of Symmetry 题解

2022/7/30 23:26:37

本文主要是介绍P3454 OSI-Axes of Symmetry 题解,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!

P3454 OSI-Axes of Symmetry 题解

求多边形的对称轴

这是一道人类智慧题

顺时针或者逆时针转一圈,将 \(n\) 个点的多边形的角和边的值连在一起就得到了一个环,环长为 \(2n\)

我们只需要判断对应的边和角相等

具体地,我们用边长表示每条边,用两条邻边的叉积和点积代表以这个点为顶点的角的大小

这样可以把多边形序列化,设序列为 \(\text S\)

用字符串匹配的那一套理论,对称轴的数量就是拿 翻转后的 \(\text S\) 到 \(\text{SS}\) 中去匹配

最后结果就是匹配点的数量,这可以用 \(kmp\) 解决

或是可以利用 \(manacher\) 的那一套理论,在 \(\text{SS}\) 中找长度 \(\ge|\text S|\) 的回文子串个数

时间复杂度 \(\text O(n)\)

然而随机化过去了

思路大概就是只有每个点或每条边的中点才可能作为答案,并且其他所有的点到这些点距离相等

然后随机枚举 \(70000\) 个点判断即可

对了,还要加个小优化

由于点都是整点,显然不会有超过 \(4\) 个对称轴

时间复杂度 \(\text O(\frac{70000n}{life\times luck})\)

某 OJ 怎么这么喜欢搬题

code

#include<bits/stdc++.h>
using namespace std;

const int N=1e5+5;

inline int read(){
	int x=0,f=1;char ch=getchar();
	while(!isdigit(ch)){if(ch=='-') f=-1;ch=getchar();}
	while(isdigit(ch)){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
	return x*f;
}

struct pt{
	double x,y;
}a[N*2];

int n;
//ad-bc
inline double dis(pt A,pt B){
	//printf("%lf %lf %lf %lf\n",A.x,A.y,B.x,B.y);
	return (A.x-B.x)*(A.x-B.x)+(A.y-B.y)*(A.y-B.y);
}

inline int rnd(int x){
	return 1ll*rand()%x*rand()%x+1;
}

bitset <N> v;

int s[N];

inline int check(int x){
	int k=(x%2)^1;
	pt qwq={0,0};
	for(int i=1;i<=70000;++i){
		int j=s[i];
		if(i>n/4) break;
		int p=(x+j*2-k),q=(x-2*j+k);
		if(q<1) q+=n;
		if(p>n) p-=n; 
		if(p==q) continue;
		if(fabs(dis(a[x],a[p])-dis(a[x],a[q]))>1e-8) return 0;
		if(i==1) qwq.x=(a[p].x+a[q].x)/2,qwq.y=(a[p].y+a[q].y)/2;
		if(i>1&&fabs(dis(qwq,a[p])-dis(qwq,a[q]))>1e-8) return 0;
	}
	return 1;
}

int p[N];

signed main(){
	srand(114514);
	int T=read();
	while(T--){
		n=read();
		for(int i=0;i<n;++i){
			scanf("%lf%lf",&a[i*2+1].x,&a[i*2+1].y);
		}
		a[n*2].x=(a[1].x+a[2*n-1].x)/2;
		a[n*2].y=(a[1].y+a[2*n-1].y)/2;
		for(int i=1;i<n;++i){
			a[i*2].x=(a[i*2-1].x+a[i*2+1].x)/2.0;
			a[i*2].y=(a[i*2-1].y+a[i*2+1].y)/2.0;
		}
		n*=2;
		int ans=0;
		for(int i=1;i*2<=n;++i) p[i]=i;
		for(int i=1;i*4<=n;++i)s[i]=i;
		random_shuffle(p+1,p+n/2+1);
		random_shuffle(s+1,s+n/4+1);
		for(int i=1;i*2<=n;++i){
			ans+=check(p[i]);
			if(ans>=4) break;
		}
		printf("%d\n",ans);
	}
}


这篇关于P3454 OSI-Axes of Symmetry 题解的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!


扫一扫关注最新编程教程