题面

给定一个多边形,求对称轴数量。

分析

初看这似乎是一道计算几何的题目,但是如果暴力枚举对称轴,再去判断对称轴两边的边和角是否相等,时间复杂度为\(O(n^2)\),显然会TLE

问题转换

顺时针转一圈,将角和边的值连在一起就得到了一个环

假如有一个边长为1的三角形,则它的角和边序列应该是:$ 1,60°,1,60°,1,60° $,围成一个环(角为环上的边,边为环上的结点)之后就

变成了:

将1记为a,60°记为b,则环变为:

而对称轴会把这些点分成两部分,且两部分完全一样,对应到序列上就是:断开环上的某一条边,且连

成的序列是回文的

环的处理

对于环上的回文问题,我们不好处理。一种常见的处理方法是选择任意一个位置断开,将序列复制成

为2n长度的链

然后我们在这条链上找长度为n的回文串

找回文串

如何找回文串?Manacher算法是一种很有效的方法,但KMP的使用范围更广。先选择任意一个位置断开,记该序列为S0,再复制一遍得到序列S,将S0反过来得到串T,求S中有多少个位置和T匹配即可

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

一些细节
  • 如何处理边和角? 边直接用长度表示(注意不必要开方,直接用长度的平方算,大量计算根号会导致TLE),而角由于考虑到图形不一定是凸多边形,采用叉积的方法记录角度,而不是点积。这里运用了叉积的性质:两向量夹角小于180°为正值,夹角大于180°为负值
  • 边和角都用long long 存储,不必用double
  • 序列S的长度为4n,序列T的长度为2n,数组不要开小了

代码

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#define maxn 100005
using namespace std;
inline void qread(int &x) {x=0;int sign=1;char c=getchar();while(c<'0'||c>'9') {if(c=='-') sign=-1;c=getchar();}while(c>='0'&&c<='9') {x=x*10+c-'0';c=getchar();}x=x*sign;
}int n;
int T;
struct point {//点 long long x;long long y;point() {}point(long long xx,long long yy) {x=xx;y=yy;}friend point operator +(point a,point b) {return point(a.x+b.x,a.y+b.y);}friend point operator -(point a,point b) {return point(a.x-b.x,a.y-b.y);}
} a[maxn];
typedef point vector;//在程序实现上,点和向量没有区别
long long dot(vector a,vector b) {//点积 return a.x*b.x+a.y*b.y;
}
long long cross(vector a,vector b) {//叉积 return a.x*b.y-a.y*b.x;
}long long dist(point a,point b) {//计算两点间距离 vector v=a-b;return dot(v,v);
}long long work_edge(int x) {//逐一处理多边形的边,注意编号为n的点下一个点是1 int y=x+1;if(y>n) y=1;return dist(a[x],a[y]);
}
long long work_ang(int x) {//处理角,同样注意编号为n的点下一个点是1 int y=x+1,z=x+2;if(y>n) y=y%n;if(z>n) z=z%n;return cross(a[y]-a[x],a[z]-a[y]);
}
long long edge[maxn];
long long ang[maxn];
long long tmp[maxn];
int s[maxn*4];
int t[maxn*2];int next[maxn*4];
int f[maxn*4];
int KMP(int *a,int n,int *b,int m) {//KMP模板 next[1]=0;for(int i=2,j=0; i<=n; i++) {while(j>0&&a[i]!=a[j+1]) j=next[j];if(a[i]==a[j+1]) j++;next[i]=j;}for(int i=2,j=0; i<=m; i++) {while(j>0&&b[i]!=a[j+1]) j=next[j];if(b[i]==a[j+1]) j++;f[i]=j;}int cnt=0;for(int i=1; i<=m; i++) {if(f[i]==n) cnt++;}return cnt;
}
int main() {int x,y;qread(T);while(T--) {qread(n);for(int i=1; i<=n; i++) {qread(x);qread(y);a[i].x=x;a[i].y=y;}for(int i=1; i<=n; i++) {edge[i]=work_edge(i);ang[i]=work_ang(i);}int newn=0;int newm=0;for(int i=1; i<=n; i++) {//由于计算的角是第i与i+1条边之间的夹角,所以先加入边,再加入角 s[++newn]=edge[i];s[++newn]=ang[i];}for(int i=1; i<=n; i++) {s[++newn]=edge[i];s[++newn]=ang[i];}for(int i=n*2; i>=1; i--) {t[++newm]=s[i];}printf("%d\n",KMP(t,newm,s,newn));}
}

转载于:https://www.cnblogs.com/birchtree/p/9861449.html

BZOJ 1100 luogu 3454(计算几何+KMP)相关推荐

  1. UOJ #219 BZOJ 4650 luogu P1117 [NOI2016]优秀的拆分 (后缀数组、ST表)

    UOJ #219 BZOJ 4650 luogu P1117 [NOI2016]优秀的拆分 (后缀数组.ST表) 连NOI Day1T1都不会做...看了题解都写不出来还要抄Claris的代码.. 题 ...

  2. UOJ #131 BZOJ 4199 luogu P2178【NOI2015】品酒大会 (后缀自动机、树形DP)

    UOJ #131 BZOJ 4199 luogu P2178[NOI2015]品酒大会 (后缀自动机.树形DP) 水是水,但是写出了不少问题,因此写一发博客. https://www.luogu.or ...

  3. UOJ #277 BZOJ 4739 定向越野 (计算几何、最短路)

    UOJ #277 BZOJ 4739 定向越野 (计算几何.最短路) 手动博客搬家: 本文发表于20181208 14:39:01, 原地址https://blog.csdn.net/suncongb ...

  4. BZOJ 1500 Luogu P2042 [NOI2005] 维护数列 (Splay)

    BZOJ 1500 Luogu P2042 [NOI2005] 维护数列 (Splay) 手动博客搬家: 本文发表于20180825 00:34:49, 原地址https://blog.csdn.ne ...

  5. BZOJ 3930 Luogu P3172 选数 (莫比乌斯反演)

    BZOJ 3930 Luogu P3172 选数 (莫比乌斯反演) 手动博客搬家:本文发表于20180310 11:46:11, 原地址https://blog.csdn.net/suncongbo/ ...

  6. POJ 1061 BZOJ 1477 Luogu P1516 青蛙的约会 (扩展欧几里得算法)

    POJ 1061 BZOJ 1477 Luogu P1516 青蛙的约会 (扩展欧几里得算法) 手动博客搬家: 本文发表于20180226 23:35:26, 原地址https://blog.csdn ...

  7. BZOJ 1101 Luogu P3455 POI 2007 Zap (莫比乌斯反演+数论分块)

    BZOJ 1101 Luogu P3455 POI 2007 Zap (莫比乌斯反演+数论分块) 手动博客搬家: 本文发表于20171216 13:34:20, 原地址https://blog.csd ...

  8. BZOJ 2152 Luogu 2634——聪聪可可

    BZOJ 2152  Luogu 2634--聪聪可可 题意 求两点之间路径和为3的倍数占的概率(最简) 解题思路与BZOJ1468差不多, 不过本题在计算经过某个点的次数时用了个ans数组, 对路径 ...

  9. BZOJ 4814 Luogu P3699 [CQOI2017]小Q的草稿 (计算几何、扫描线、set)

    题目链接 (BZOJ) http://lydsy.com/JudgeOnline/problem.php?id=4814 (Luogu) https://www.luogu.org/problem/P ...

  10. BZOJ 1859 Luogu P2589 [ZJOI2006]碗的叠放 (计算几何)

    woc, 13年前的ZJOI就这么毒瘤的嘛... 题目链接: (bzoj)https://www.lydsy.com/JudgeOnline/problem.php?id=1859 (luogu)ht ...

最新文章

  1. 轻松一下,看看vs.net2002变态的智能提示,不知道算不算bug
  2. Nginx 高可用集群解决方案 Nginx + Keepalived
  3. android 8.0的imei简书,Android 8.0通知栏渠道,渠道组的适配和使用
  4. SpringBoot测试时出现Whitelabel Error Page
  5. linux内核镜像解压,解压内核镜像
  6. win7win10 配置wlan热点
  7. HTML+CSS+JS实现 贪吃蛇游戏源码
  8. Ubuntu16.04安装使用wineqq
  9. AD、DHCP、DNS概念整理
  10. Google 开通免费主机服务,如果你有email帐户,你就可以注册,目前最多只能存放40页面...
  11. JAVA电子书大礼包
  12. 含泪推荐5款极为实用的软件
  13. QT设置按钮QPushButton上图片加文字
  14. 文件下载之断点续传(客户端与服务端的实现)
  15. MFC实现程序开机自动运行
  16. 《ERP高级计划》书的解读- APS算法分析之四约束规划CP(蔡颖)(转)
  17. 前端学习之路(1)———表格的增行和减行
  18. libGDX学习之路02:利用Tiled绘制游戏地图
  19. Linux配置ssh远程连接服务
  20. 前端:margin、padding、float一篇文章彻底理解

热门文章

  1. android runtime异常,在做android下拉刷新时遇到异常java.lang.RuntimeException: Can't create handle...
  2. php+ci+db+debug,[PHP] Web Framework : CodeIgniter MySQL Database 使用教學
  3. feign扫描_微服务实战SpringCloud之Feign简介及使用
  4. ctf 改变图片高度_在Unity中 改变地形(Terrain),并加上水面、树、草地、材质(地板上色)...
  5. hdoj1087:Super Jumping! Jumping! Jumping!(dp基础题-最大上升子序列和(可不连续))
  6. STM32——库函数版——超声波测距模块(HC-SR04)
  7. 滚动率分析(Roll Rate Analysis)
  8. websocket 连接本地端口_Spring Boot 结合 WebSocket 实现在线聊天
  9. 计算机电路基础电压比较器电路图,计算机电路基础期末复习.doc
  10. linux查找文件并显示修改时间,linux下find命令和文件的三种时间