BZOJ 1100 POI2007 对称轴osi 计算几何+KMP算法

来源:互联网 发布:信用卡和淘宝账号贷款 编辑:程序博客网 时间:2024/04/30 03:06

题目大意:给定一个多边形,求对称轴数量

我X 这究竟是怎么想到KMP的……

首先 将边字符化 即找到这个多边形的中心 然后用与中心构成的三角形的边-角-边的方式表示这条边

将边顺时针扫一遍 然后倍增至长度为2n-1 再逆时针扫一遍 逆时针扫的那遍在顺时针那遍中出现的次数就是对称轴数目

用KMP算法就能搞出来 证明自己YY吧

出题人卡精度丧心病狂。。。

#include <cmath>#include <cstdio>#include <cstring>#include <iostream>#include <algorithm>#define M 100100#define EPS 1e-6using namespace std;struct point{double x,y;point(){}point(double _,double __):x(_),y(__){}void Read(){scanf("%lf%lf",&x,&y);}void operator += (const point &Y){x+=Y.x;y+=Y.y;}point operator - (const point &Y) const{return point(x-Y.x,y-Y.y);}double operator * (const point &Y) const{return x*Y.y-Y.x*y;}point operator / (double a) const{return point(x/a,y/a);}}points[M],centre;struct line{double d1,d2,cross;line(){}line(double _,double __,double ___):d1(_),d2(__),cross(___/_/__){}bool operator == (const line &Y) const;}a[M],b[M<<1];int n;bool line :: operator == (const line &Y) const{if(fabs(d1-Y.d1)>EPS)return false;if(fabs(d2-Y.d2)>EPS)return false;if(fabs(cross-Y.cross)>EPS)return false;return true;}double Distance(const point &p1,const point &p2){return sqrt( (p1.x-p2.x)*(p1.x-p2.x) + (p1.y-p2.y)*(p1.y-p2.y) );}int KMP(int len){static int next[M];int i,fix=0,re=0;for(i=2;i<=n;i++){while( fix && !(a[fix+1]==a[i]) )fix=next[fix];if( a[fix+1]==a[i] ) ++fix;next[i]=fix;}fix=0;for(i=1;i<=len;i++){while( fix && !(a[fix+1]==b[i]) )fix=next[fix];if( a[fix+1]==b[i] ) ++fix;if(fix==n)++re,fix=next[fix];}return re;}int main(){//freopen("osi.in","r",stdin);//freopen("osi.out","w",stdout);int T;for(cin>>T;T;T--){int i;cin>>n;centre=point(0.0,0.0);for(i=1;i<=n;i++)points[i].Read(),centre+=points[i]/static_cast<double>(n);for(i=1;i<=n;i++)b[i]=b[i+n]=line(Distance(points[i],centre),Distance(points[i%n+1],centre), (points[i]-centre)*(points[i%n+1]-centre) );for(i=n;i;i--)a[n-i+1]=line(b[i].d2,b[i].d1,0),a[n-i+1].cross=b[i].cross;cout<<KMP(n+n-1)<<endl;}}


0 0
原创粉丝点击