补题向 | The Supersonic Rocket(凸包+KMP)

The Supersonic Rocket

求由n个点和m个点构成的两个凸包能不能重叠

如果两个凸包边长度和角大小相同,则能重合,所以先建凸包,然后按顺序保存点乘大小(!!不能用叉积[sin],180度内各个角点乘大小[cos]不相等)和边长度,然后对比两序列

#include<stdio.h>
#include<vector>
#include<algorithm>
#include<string.h>
#include<iostream>
#include<fstream>
#include<math.h>
#include<stack>
#include<bitset>
#include<utility>
using namespace std;
typedef long long ll;
const double eps=0.0000000000001;
const int mod=1000000007;
int n,m;
vector<double> cra;
vector<double> crb;

struct P{
	ll x;
	ll y;
	P(){}
    P(ll _x,ll _y){
        x = _x;y = _y;
    }
	P operator -(const P &b)const{
        return P(x - b.x,y - b.y);
    }
};
P ps[100005];
int nt[1000005];

bool cmp_p(P a,P b){
	if(a.x==b.x)return a.y<b.y;
	else return a.x<b.x;
}
double dot(P b,P a,P c){
    return (b.x-a.x)*(c.x-a.x)+(b.y-a.y)*(c.y-a.y);
}
double cross(P b,P a,P c){
    return (b.x-a.x)*(c.y-a.y)-(b.y-a.y)*(c.x-a.x);
}
double dist(P a,P b){
	return (b.x-a.x)*(b.x-a.x)+(b.y-a.y)*(b.y-a.y);
}

void gch(P*p,int nl,vector<double> &cr){
	sort(p,p+nl,cmp_p);
	vector<P> ch(nl*2);
	int k=0;
	for(int i=0;i<nl;i++){
		while(k>1&&cross(ch[k-2],ch[k-1],p[i])<=0)k--;
		ch[k]=p[i];
		k++;
	}
	for(int i=nl-2,t=k;i>=0;i--){
		while(k>t&&cross(ch[k-2],ch[k-1],ps[i])<=0)k--;
		ch[k]=p[i];
		k++;
	}
	ch.resize(k-1);
	k--;
	for(int i=1;i<k-1;i++){
		cr.push_back(dist(ch[i-1],ch[i]));
		cr.push_back(dot(ch[i-1],ch[i],ch[i+1]));
	}
	cr.push_back(dist(ch[k-2],ch[k-1]));
	cr.push_back(dot(ch[k-2],ch[k-1],ch[0]));
	cr.push_back(dist(ch[k-1],ch[0]));
	cr.push_back(dot(ch[k-1],ch[0],ch[1]));
	/*
	for(int i=0;i<cr.size();i++){
		cout<<cr[i]<<" ";
	}
	cout<<endl;
	*/
}
void gnt(vector<double> &b){
	int bl=b.size();
	int k=-1;
	int i=0;
	nt[0]=-1;
	while(i<bl){
		if(k==-1||b[k]==b[i]){
			i++;k++;
			nt[i]=k;
		}
		else{
			k=nt[k];
		}
	}
}
bool KMP(vector<double> &a,vector<double> &b){
	int al=a.size();
	int bl=b.size();
	//cout<<al<<" "<<bl;
	if(al!=bl)return false;
	int i=0;
	int j=0;
	int flag=0;
	while(j<bl){
		if(i==al){
			i=0;
		}
		if(i==0&&j==0){
			flag++;
		}
		if(flag==2)break;
		if(j==-1||a[i]==b[j]){
			i++;
			j++;
		}
		else{
			j=nt[j];
		}
	}
	if(j==bl)return true;
	else return false;
}
int main(){
	scanf("%d%d",&n,&m);
	ll a,b;
	for(int i=0;i<n;i++){
		scanf("%I64d%I64d",&a,&b);
		ps[i].x=a;
		ps[i].y=b;
	}
	
	gch(ps,n,cra);

	for(int i=0;i<m;i++){
		scanf("%I64d%I64d",&a,&b);
		ps[i].x=a;
		ps[i].y=b;
	}
	
	gch(ps,m,crb);
	gnt(crb);
	
	if(KMP(cra,crb)){
		printf("YES\n");
	}
	else{
		
		printf("NO\n");
	}
	return 0;
}

忘记KMP时要循环比较,RTE了很久,坑的是样例输出正确,dev也不报错,愣是没看出来

( _ _)ノ|

猜你喜欢

转载自blog.csdn.net/bekote/article/details/81632302