hdu 4613 Points( KMP 图形学)

http://acm.hdu.edu.cn/showproblem.php?pid=4613


这题感觉有点坑爹,虽然不难推出解法,但实现起来debug到死

取点集的中心,向其他点作向量;

根据各个向量算出向量长度和角坐标,排序;

将需要匹配的点集以同样方法处理,并一致化向量长度;

考虑翻转后的匹配;

重载运算符 kmp匹配

注意点:与中心重合的点必须去掉,否则会干扰翻转后的匹配

#include<cstdio>
#include<algorithm>
#include<vector>
#include<cmath>
#include<iostream>
#include<queue>
#pragma comment(linker, "/STACK:1024000000,1024000000")
using namespace std;
const int MAXN = 25005;
const double eps = 1e-8;
const double pi = acos(-1.0);
int nx0[MAXN], nx1[MAXN];
inline int cmp(const double a, const double b)
{return (a-b>eps) - (a-b<-eps);}
struct vctor
{
    double x, y;
    double agl, dis; /* 0 ~ 2pi */
    void build()
    {
        dis = sqrt(x*x + y*y);
        agl = atan2(y, x);
        if (agl < 0) agl += 2*pi;
    }
    bool operator < (const vctor & in) const
    {
        if (cmp(agl, in.agl) == 0) return dis<in.dis;
        return agl < in.agl;
    }
    bool operator == (const vctor & in) const
    {
        return cmp(agl, in.agl) == 0 && cmp(dis, in.dis) == 0;
    }
    void getin() {scanf("%lf%lf", &x, &y);}
};
struct _data
{
    int n;
    vctor pp[MAXN*2], md0;
    double sd;
    void getda()
    {
        scanf("%d", &n);
        md0.x = md0.y = 0.0;
        for (int i = 0; i< n; ++i) 
        {
            pp[i].getin();
            md0.x += pp[i].x;
            md0.y += pp[i].y;
        }
        md0.x /= n; md0.y /= n;
    }
    void initda(int cs = 1)
    {        
        double dtp;
        int itp = 0;
        sd = 0.0;
        for (int j = 0; j< n; ++j)
        {
            pp[j].x -= md0.x; pp[j].y -= md0.y;
            pp[j].build();
            /* important !!!!!*/
            if (cmp(pp[j].dis, 0.0))
            	pp[itp++] = pp[j];
        }
        n = itp;
        sort(pp, pp+n);
        dtp = pp[n-1].agl;
        for (int i = n-1; i>= 1; pp[i].agl -= pp[(i--)-1].agl);
        pp[0].agl += 2*pi-dtp;
        if (cs)
        for (int i = 0; i< n; ++i) sd += pp[i].dis;
    }
}da, db, dc;
void getpre(int n, int pre[], vctor pp[])
{
    pre[0] = -1;
    for (int i = 1, j=-1; i< n; ++i)
    {
        while(j > -1 && !(pp[j+1] == pp[i])) j = pre[j];
        if (pp[j+1] == pp[i]) ++j;
        pre[i] = j;
    }
}
inline void ot(int g)
{
    if (g) puts("Yes");
    else puts("No");
}
int kmp(vctor p[], vctor q[], int n, int m, int next[])
{
    for (int i = 0, j = 0; i< n; )
    {
        if (j == -1 || p[i] == q[j])
            ++j,++i;
        else j = next[j];
        if (j == m)
            return 1;
    }
    return 0;
}
int solve(int s)
{
	db.getda();
	if (db.n != s) return 0;
	if (s < 3) return 1;
    db.initda();
    if (db.n != da.n) return 0;
    double be = da.sd / db.sd;
    for (int i = 0; i< db.n; ++i) db.pp[i].dis *= be;
    for (int i = 0; i< db.n; ++i) db.pp[db.n+i] = db.pp[i];
    if (kmp(db.pp, da.pp, db.n*2, da.n, nx0) || 
		kmp(db.pp, dc.pp, db.n*2, dc.n, nx1))
		return 1;
	else
		return 0;
}
int main()
{
#ifndef ONLINE_JUDGE
    freopen("in.txt", "r", stdin);
#endif
    int t, k, s;
    scanf("%d", &t);
    while(t--)
    {
        da.getda();
        s = da.n;
        dc = da;
        for (int i = 0; i< dc.n; ++i) dc.pp[i].x = -dc.pp[i].x;
        dc.md0.x = -dc.md0.x;
        da.initda();
        dc.initda(0);
        getpre(da.n, nx0, da.pp);
        getpre(dc.n, nx1, dc.pp);
        scanf("%d", &k);
        while(k--)
			ot(solve(s));
        puts("");
    }
    return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值