• BZOJ1100: [POI2007]对称轴osi


    BZOJ1100: [POI2007]对称轴osi

    Description

    FGD小朋友——一个闻名遐迩的年轻数学家——有一个小MM,yours。

    FGD小朋友非常喜欢他的MM,所以他很乐意帮助他的MM做数学作业。

    但是,就像所有科学的容器一样,FGD的大脑拒绝不停地重复思考同样的问题。

    不幸的是,yours是一个十分用功的学生,所以她不停地让FGD帮助她检查她的作业。

    一个阳光明媚的周末,yours的数学老师布置了非常多的寻找多边形的对称轴的题,足够她做相当长的一段时间了。

    在此之前FGD已经决定去海边度过这个难得的假期,不过他还是觉得应该帮助他的MM对付可爱的数学作业。

    很快地,他找到了解决方案,最好写一个程序来帮助yours检查她的数学作业。

    因为FGD并非一个计算机科学家,所以他找到了他的好朋友你,请你帮助他完成这个任务。

    请写一个程序:读入多边形的描述计算出每个多边形的对称轴数将计算的结果输出

    Input

      输入的第一行包含一个正整数t(1<=t<=10),为多边形的边数。

    接下来,为t个多边形的描述,每个描述的第一行为一个正整数n(3<=n<=100000),表示了多边形的点数。

    然后在后面n行每行两个整数x和y(?100000000<=x, y<=100000000),依次表示多边形的顶点坐标。

    多边形不一定是凸的,但是不自交——任何两条边都只有最多一个公共点——他们的公共端点。

    此外,没有两条连续的边平行。

    Output

      你的程序应该输出正好t行,第k行包含了一个整数nk——表示第k个多边形有多少个对称轴。

    Sample Input

    2
    12
    1 -1
    2 -1
    2 1
    1 1
    1 2
    -1 2
    -1 1
    -2 1
    -2 -1
    -1 -1
    -1 -2
    1 -2
    6
    -1 1
    -2 0
    -1 -1
    1 -1
    2 0
    1 1

    Sample Output

    4
    2

    HINT


    题解Here!

    这是一道神题!

    题目要求:求多边形的对称轴条数。

    乍一看,一道有思维难度的计算几何——先求出凸包,然后开始旋转卡壳。

    但是这题比较好玩,不用这么麻烦:

    将每一个边和角(叉积)$hash$一下,然后就会得到一个字串,对这个字串跑一遍最长回文子串,其长度即为对称轴数量。

    我当时看到这个做法时第一反应:吼啊!妙啊!神奇啊!

    至于最长回文子串怎么求,就丢给了$O(n)$的$Manacher$。。。

    注:附加多组询问。

    附代码:

    #include<iostream>
    #include<algorithm>
    #include<cstdio>
    #include<cmath>
    #include<cstring>
    #define MAXN 100010
    using namespace std;
    int n,m,p[MAXN<<3],s[MAXN<<3];
    struct Point{
    	int x,y;
    }a[MAXN];
    inline int read(){
    	int date=0,w=1;char c=0;
    	while(c<'0'||c>'9'){if(c=='-')w=-1;c=getchar();}
    	while(c>='0'&&c<='9'){date=date*10+c-'0';c=getchar();}
    	return date*w;
    }
    inline int dis(int i,int j){
    	return (a[i].x-a[j].x)*(a[i].x-a[j].x)+(a[i].y-a[j].y)*(a[i].y-a[j].y);
    }
    inline int cross(int i,int j,int k){
    	return (a[i].x-a[k].x)*(a[j].y-a[k].y)-(a[j].x-a[k].x)*(a[i].y-a[k].y);
    }
    void buildstring(){
    	for(int i=0;i<n;i++){
    		s[i<<1]=cross((i-1+n)%n,(i+1)%n,i);
    		s[i<<1|1]=dis(i,(i+1)%n);
    	}
    	m=n<<1;
    	for(int i=0;i<n;i++)s[i+m]=s[i];
    	m<<=1;
    }
    void manacher(){
    	int ans=0,maxn=0,id;
    	for(int i=0;i<m;i++){
    		if(maxn>i)p[i]=min(p[id*2-i],p[id]+id-i);
    		else p[i]=1;
    		for(;i-p[i]>=0&&i+p[i]<=m&&s[i+p[i]]==s[i-p[i]];p[i]++);
    		if(p[i]+i>maxn){
    			maxn=p[i]+i;
    			id=i;
    		}
    		if(p[i]>=n+1)ans++;
    	}
    	printf("%d
    ",ans);
    }
    void work(){
    	buildstring();
    	manacher();
    }
    void init(){
    	n=read();
    	memset(a,0,sizeof(a));
    	memset(p,0,sizeof(p));
    	memset(s,0,sizeof(s));
    	for(int i=0;i<n;i++){a[i].x=read();a[i].y=read();}
    }
    int main(){
    	int t=read();
    	while(t--){
    		init();
    		work();
    	}
    	return 0;
    }
    
  • 相关阅读:
    SpringCloud学习(三)服务消费者(Feign)(Finchley版本)
    go爬虫系列
    SpringCloud学习(二)服务消费者(rest+ribbon)(Finchley版本)
    SpringCloud学习(一)服务的注册与发现Eureka(Finchley版本)
    JDK源码分析(11) ConcurrentLinkedQueue
    ServiceFabric极简文档-4.1 学习路线图
    ServiceFabric极简文档-4.0 开发环境搭建
    ServiceFabric极简文档-3. 发布脚本
    ServiceFabric极简文档-2 部署环境搭建-配置文件
    ServiceFabric极简文档-1.3删除群集
  • 原文地址:https://www.cnblogs.com/Yangrui-Blog/p/9840505.html
Copyright © 2020-2023  润新知