CodeForces - 1017E :The Supersonic Rocket (几何+KMP,判定凸包是否同构)
After the war, the supersonic rocket became the most common public transportation.
Each supersonic rocket consists of two "engines". Each engine is a set of "power sources". The first engine has nn power sources, and the second one has mm power sources. A power source can be described as a point (xi,yi)(xi,yi) on a 2-D plane. All points in each engine are different.
You can manipulate each engine separately. There are two operations that you can do with each engine. You can do each operation as many times as you want.
- For every power source as a whole in that engine: (xi,yi)(xi,yi) becomes (xi+a,yi+b)(xi+a,yi+b), aa and bb can be any real numbers. In other words, all power sources will be shifted.
- For every power source as a whole in that engine: (xi,yi)(xi,yi) becomes (xicosθ−yisinθ,xisinθ+yicosθ)(xicosθ−yisinθ,xisinθ+yicosθ), θθ can be any real number. In other words, all power sources will be rotated.
The engines work as follows: after the two engines are powered, their power sources are being combined (here power sources of different engines may coincide). If two power sources A(xa,ya)A(xa,ya) and B(xb,yb)B(xb,yb) exist, then for all real number kk that 0<k<10<k<1, a new power source will be created Ck(kxa+(1−k)xb,kya+(1−k)yb)Ck(kxa+(1−k)xb,kya+(1−k)yb). Then, this procedure will be repeated again with all new and old power sources. After that, the "power field" from all power sources will be generated (can be considered as an infinite set of all power sources occurred).
A supersonic rocket is "safe" if and only if after you manipulate the engines, destroying any power source and then power the engine, the power field generated won't be changed (comparing to the situation where no power source erased). Two power fields are considered the same if and only if any power source in one field belongs to the other one as well.
Given a supersonic rocket, check whether it is safe or not.
Input
The first line contains two integers nn, mm (3≤n,m≤1053≤n,m≤105) — the number of power sources in each engine.
Each of the next nn lines contains two integers xixi and yiyi (0≤xi,yi≤1080≤xi,yi≤108) — the coordinates of the ii-th power source in the first engine.
Each of the next mm lines contains two integers xixi and yiyi (0≤xi,yi≤1080≤xi,yi≤108) — the coordinates of the ii-th power source in the second engine.
It is guaranteed that there are no two or more power sources that are located in the same point in each engine.
Output
Print "YES" if the supersonic rocket is safe, otherwise "NO".
You can print each letter in an arbitrary case (upper or lower).
Examples
3 4
0 0
0 2
2 0
0 2
2 2
2 0
1 1
YES
3 4
0 0
0 2
2 0
0 2
2 2
2 0
0 0
NO
Note
The first sample:
Those near pairs of blue and orange points actually coincide.
First, manipulate the first engine: use the second operation with θ=πθ=π (to rotate all power sources 180180 degrees).
The power sources in the first engine become (0,0)(0,0), (0,−2)(0,−2), and (−2,0)(−2,0).
Second, manipulate the second engine: use the first operation with a=b=−2a=b=−2.
The power sources in the second engine become (−2,0)(−2,0), (0,0)(0,0), (0,−2)(0,−2), and (−1,−1)(−1,−1).
You can examine that destroying any point, the power field formed by the two engines are always the solid triangle (0,0)(0,0), (−2,0)(−2,0), (0,−2)(0,−2).
In the second sample, no matter how you manipulate the engines, there always exists a power source in the second engine that power field will shrink if you destroy it.
题意:题面很长,但其实就是给定两个多边形,问其凸包是否旋转同构。
思路:先得到两个多边形的凸包,然后把多边形看成字符串,而判定字符串S1和S2旋转同构的方法是,将S1加倍,去匹配S2,KMP即可搞定。
现在把多边形像字符串一样保存,角-边-角-边...,而角可以用点乘表示,因为角两旁的边相等,而点乘也相同,说明角度相同。而叉积不具有这样的性质,平行四边形的相邻角就是反例。
(hash也可以判定旋转同构
#include<bits/stdc++.h>
using namespace std;
#define mp make_pair
typedef long long ll;
const double inf=1e200;
const double eps=1e-;
const double pi=*atan(1.0);
struct point{
double x,y;
point(double a=,double b=):x(a),y(b){}
};
int dcmp(double x){ return fabs(x)<eps?:(x<?-:);}
point operator +(point A,point B) { return point(A.x+B.x,A.y+B.y);}
point operator -(point A,point B) { return point(A.x-B.x,A.y-B.y);}
point operator *(point A,double p){ return point(A.x*p,A.y*p);}
point operator /(point A,double p){ return point(A.x/p,A.y/p);}
point rotate(point A,double rad){
return point(A.x*cos(rad)-A.y*sin(rad), A.x*sin(rad)+A.y*cos(rad));
}
bool operator ==(const point& a,const point& b) {
return dcmp(a.x-b.x)==&&dcmp(a.y-b.y)==;
}
double dot(point A,point B){ return A.x*B.x+A.y*B.y;}
double det(point A,point B){ return A.x*B.y-A.y*B.x;}
double dot(point O,point A,point B){ return dot(A-O,B-O);}
double det(point O,point A,point B){ return det(A-O,B-O);}
/*double length(point A){ return sqrt(dot(A,A));}
double angle(point A,point B){ return acos(dot(A,B)/length(A)/length(B));}
double distoline(point P,point A,point B)
{
//点到直线距离
point v1=B-A,v2=P-A;
return fabs(det(v1,v2)/length(v1));
}
double distoseg(point P,point A,point B)
{
//点到线段距离
if(A==B) return length(P-A);
point v1=B-A,v2=P-A,v3=P-B;
if(dcmp(dot(v1,v2))<0) return length(v2);
else if(dcmp(dot(v1,v3))>0) return length(v3);
return fabs(det(v1,v2)/length(v1));
}
double Ployarea(vector<point>p)
{
//多边形面积
double ans=0; int sz=p.size();
for(int i=1;i<sz-1;i++) ans+=det(p[i]-p[0],p[i+1]-p[0]);
return ans/2.0;
}
bool SegmentProperIntersection(point a1,point a2,point b1,point b2) {
//规范相交
double c1=det(a2-a1,b1-a1),c2=det(a2-a1,b2-a1);
double c3=det(b2-b1,a1-b1),c4=det(b2-b1,a2-b1);
return dcmp(c1)*dcmp(c2)<0&&dcmp(c3)*dcmp(c4)<0;
}
bool isPointOnSegment(point p,point a1,point a2)
{
//点是否在线段上
return dcmp(det(a1-p,a2-p)==0&&dcmp(dot(a1-p,a2-p))<0);
}
int isPointInPolygon(point p,vector<point>poly)
{
//判断点与多边形的位置关系
int wn=0,sz=poly.size();
for(int i=0;i<sz;i++){
//在边上
if(isPointOnSegment(p,poly[i],poly[(i+1)%sz])) return -1;
int k=dcmp(det(poly[(i+1)%sz]-poly[i],p-poly[i]));
int d1=dcmp(poly[i].y-p.y); int d2=dcmp(poly[(i+1)%sz].y-p.y);
if(k>0&&d1<=0&&d2>0) wn++;
if(k<0&&d2<=0&&d1>0) wn--;
}
if(wn!=0) return 1;//内部
return 0; //外部
}
double seg(point O,point A,point B){
if(dcmp(B.x-A.x)==0) return (O.y-A.y)/(B.y-A.y);
return (O.x-A.x)/(B.x-A.x);
}
pair<double,int>s[110*60];
double polyunion(vector<point>*p,int N){ //有多个才加*,单个不加,有改变的加&
//求多边形面积并
double res=0;
for(int i=0;i<N;i++){
int sz=p[i].size();
for(int j=0;j<sz;j++){
int m=0;
s[++m]=mp(0,0);
s[++m]=mp(1,0);
point a=p[i][j],b=p[i][(j+1)%sz];
for(int k=0;k<N;k++){
if(i!=k){
int sz2=p[k].size();
for(int ii=0;ii<sz2;ii++){
point c=p[k][ii],d=p[k][(ii+1)%sz2];
int c1=dcmp(det(b-a,c-a));
int c2=dcmp(det(b-a,d-a));
if(c1==0&&c2==0){
if(dcmp(dot(b-a,d-c))){
s[++m]=mp(seg(c,a,b),1);
s[++m]=mp(seg(c,a,b),-1);
}
}
else{
double s1=det(d-c,a-c);
double s2=det(d-c,b-c);
if(c1>=0&&c2<0) s[++m]=mp(s1/(s1-s2),1);
else if(c1<0&&c2>=0) s[++m]=mp(s1/(s1-s2),-1);
}
}
}
}
sort(s+1,s+m+1);
double pre=min(max(s[1].first,0.0),1.0),now,sum=0;
int cov=s[0].second;
for(int j=2;j<=m;j++){
now=min(max(s[j].first,0.0),1.0);
if(!cov) sum+=now-pre;
cov+=s[j].second;
pre=now;
}
res+=det(a,b)*sum;
}
}
return -(res/2);
}
point jiaopoint(point p,point v,point q,point w)
{ //p+tv q+tw,点加向量表示直线,求直线交点
point u=p-q;
double t=det(w,u)/det(v,w);
return p+v*t;
}
point GetCirPoint(point a,point b,point c)
{
point p=(a+b)/2; //ad中点
point q=(a+c)/2; //ac中点
point v=rotate(b-a,pi/2.0),w=rotate(c-a,pi/2.0); //中垂线的方向向量
if (dcmp(length(det(v,w)))==0) //平行
{
if(dcmp(length(a-b)+length(b-c)-length(a-c))==0) return (a+c)/2;
if(dcmp(length(b-a)+length(a-c)-length(b-c))==0) return (b+c)/2;
if(dcmp(length(a-c)+length(c-b)-length(a-b))==0) return (a+b)/2;
}
return jiaopoint(p,v,q,w);
}
void MinCircular()
{
//最小圆覆盖 ,看起来是O(N^3),期望复杂度为O(N)
point P[10000]; int n;
random_shuffle(P+1,P+n+1); //随机化
point c=P[1]; double r=0; //c 圆心,,//r 半径
for (int i=2;i<=n;i++)
if (dcmp(length(c-P[i])-r)>0) //不在圆内
{
c=P[i],r=0;
for (int j=1;j<i;j++)
if (dcmp(length(c-P[j])-r)>0)
{
c=(P[i]+P[j])/2.0;
r=length(c-P[i]);
for (int k=1;k<j;k++)
if (dcmp(length(c-P[k])-r)>0)
{
c=GetCirPoint(P[i],P[j],P[k]);
r=length(c-P[i]);
}
}
}
}*/
const int maxn=;
bool cmp(point a,point b){ return a.x==b.x?a.y<b.y:a.x<b.x; }
point f[maxn],c[maxn],ch[maxn][]; int top1,top2,L1,L2;
void convexhull(point *a,int n,int &top,int opt)
{
//水平序的Andrew算法求凸包。
sort(a+,a+n+,cmp); top=;
for(int i=;i<=n;i++){ //求下凸包
while(top>=&&det(ch[top-][opt],ch[top][opt],a[i])<=) top--;
ch[++top][opt]=a[i];
}
int ttop=top;
for(int i=n-;i>=;i--){ //求上凸包
while(top>ttop&&det(ch[top-][opt],ch[top][opt],a[i])<=) top--;
ch[++top][opt]=a[i];
}
}
double a[maxn],b[maxn]; int Next[maxn];
bool KMP()
{
Next[]=;
for(int i=,k=;i<=L2;i++){
while(k&&b[i]!=b[k+]) k=Next[k];
if(b[i]==b[k+]) k++; Next[i]=k;
}
for(int i=,k=;i<=L1+L1;i++){
while(k&&a[i]!=b[k+]) k=Next[k];
if(a[i]==b[k+]) k++;
if(k==L2) return true;
}
return false;
}
int main()
{
int N,M,i;
scanf("%d%d",&N,&M);
for(i=;i<=N;i++) scanf("%lf%lf",&f[i].x,&f[i].y);
for(i=;i<=M;i++) scanf("%lf%lf",&c[i].x,&c[i].y);
convexhull(f,N,top1,);
convexhull(c,M,top2,);
if(top1!=top2) return puts("NO"),;
for(i=;i<top1;i++){
a[++L1]=dot(ch[i][],ch[i-==?top1-:i-][],ch[i+][]);
a[++L1]=(ch[i+][].x-ch[i][].x)*(ch[i+][].x-ch[i][].x)+(ch[i+][].y-ch[i][].y)*(ch[i+][].y-ch[i][].y);
}
for(i=;i<top2;i++){
b[++L2]=dot(ch[i][],ch[i-==?top2-:i-][],ch[i+][]);
b[++L2]=(ch[i+][].x-ch[i][].x)*(ch[i+][].x-ch[i][].x)+(ch[i+][].y-ch[i][].y)*(ch[i+][].y-ch[i][].y);
}
for(i=;i<=L1;i++) a[i+L1]=a[i];
if(KMP()) puts("YES");
else puts("NO");
return ;
}
CodeForces - 1017E :The Supersonic Rocket (几何+KMP,判定凸包是否同构)的更多相关文章
- Codeforces 1017E The Supersonic Rocket 凸包,计算几何,字符串,KMP
原文链接https://www.cnblogs.com/zhouzhendong/p/CF1017E.html 题目传送门 - CF1017E 题意 给定两个点集,并构成两个凸包. 问这两个凸包是否可 ...
- E. The Supersonic Rocket Codeforces Round #502 (in memory of Leopoldo Taravilse, Div. 1 + Div. 2)
http://codeforces.com/contest/1017/problem/E 凸包模板+kmp #include <cstdio> #include <cstdlib&g ...
- Codeforces Round #502 (in memory of Leopoldo Taravilse, Div. 1 + Div. 2) E. The Supersonic Rocket
这道题比赛之后被重新加了几个case,很多人现在都过不了了 算法就是先求凸包,然后判断两个凸包相等 我们可以吧凸包序列化为两点距离和角度 角度如果直接拿向量的叉积是不对的,,因为钝角和锐角的叉积有可能 ...
- CodeForces 471D MUH and Cube Walls -KMP
Polar bears Menshykov and Uslada from the zoo of St. Petersburg and elephant Horace from the zoo of ...
- codeforces 825F F. String Compression dp+kmp找字符串的最小循环节
/** 题目:F. String Compression 链接:http://codeforces.com/problemset/problem/825/F 题意:压缩字符串后求最小长度. 思路: d ...
- Codeforces Gym100502H:Clock Pictures(KMP算法)
http://codeforces.com/gym/100502/attachments 题意:有两个时钟上面有n个指针,给出的数字代表指针的角度.问能否在某一时刻使得两个时钟的指针重合. 思路:容易 ...
- Codeforces 235C Cyclical Quest 字符串 SAM KMP
原文链接https://www.cnblogs.com/zhouzhendong/p/CF235C.html 题目传送门 - CF235C 题意 给定一个字符串 $s$ ,多组询问,每组询问的形式为 ...
- CodeForces - 1093D:Beautiful Graph(二分图判定+方案数)
题意:给定无向图,让你给点加权(1,2,3),使得每条边是两端点点权和维奇数. 思路:一个连通块是个二分图,判定二分图可以dfs,并查集,2-sat染色. 这里用的并查集(还可以带权并查集优化一下,或 ...
- Codeforces 808G Anthem of Berland【KMP】【DP】
LINK 简要题意 给你一个串s,上面有字母和一些通配符,问你将通配符换成字母之后最多可以出现多少次串t 首先有一个很傻子的做法就是\(dp_{i,j}\)表示s到第i个位置匹配t串前j个字符的完整t ...
随机推荐
- linux 下配置jdk
去java官方地址下载相应的源码包我下载的是1.8.0放在usr/local目录下 export JAVA_HOME=/usr/local/jdk1.8.0export PATH=$JAVA_HOME ...
- Windows7 配置两个版本的java环境,可自由切换
1. 准备工作 下载jdk: jdk1.7[http://www.oracle.com/technetwork/java/javase/downloads/java-archive-downloads ...
- EasyNVR无插件直播服务器播放页面的集成----单独的播放器样式
背景需求: EasyNVR自身拥有独立的客户端体系,安卓和IOS拥有各自独立的APP, 安卓下载地址:https://fir.im/EasyNVR: IOS下载可直接在APPstore搜索EasyNV ...
- Android异步载入全解析之使用AsyncTask
Android异步载入全解析之使用AsyncTask 概述 既然前面提到了多线程,就不得不提到线程池,通过线程池,不仅能够对并发线程进行管理.更能够提高他们运行的效率.优化整个App.当然我们能够自己 ...
- Kattis - triangle 【数学】
题意 求第N个迭代三角形 中 所有黑色三角形的周长的整数部分的位数 思路 该三角形的周长是 3^(n + 1)/ 2 ^ (n) 然后 可以用 long double 存下来 再求位数 就可以 AC ...
- swift ! 和 ? 的学习
刚开始学 这两个符号 不确定到底是否是可以互相替代 用的都混淆了 今天好好做个总结 如果声明一个变量 如下 var name:String? //只声明 没做初始化赋值 说明 当前name 是 n ...
- flex 组件重写 组件生命周期
AS方式重写组件常规步骤 1.如果有必要,为组件创建所有基于标记(tag-based)的皮肤(skins) 2.创建ActionScript类文件 ⑴从一个基类扩展,比如UIComponent或者其他 ...
- nodejs模块之http&&url
我们使用nodejs中的http模块来进行网络操作 一.什么是HTTP协议: 超文本传输协议(HyperText Transfer Protocol)HTTP假定其下层协议提供可靠传输. 因此,任何能 ...
- 【Flask模板】include标签
# include标签:1. 这个标签相当于是直接将指定的模版中的代码复制粘贴到当前位置.2. `include`标签,如果想要使用父模版中的变量,直接用就可以了,不需要使用`with context ...
- mini2440移植uboot 2011.03(上)
参考博文: <u-boot-2011.03在mini2440/micro2440上的移植> 本来我想移植最新版的uboot,但是移植却不太成功,所以先模仿他人的例子重新执行一遍,对uboo ...