关闭

程序设计天梯赛——迎风一刀斩

标签: 几何
673人阅读 评论(0) 收藏 举报
分类:

题目链接https://www.patest.cn/contests/gplt/L3-006

首先 设两个多边形为A和B 

由于存在翻面操作 所以可以改为分别判断A与B 和A与(B的翻面)

同理可以对B进行旋转操作,将B分成8个B' 分别和A进行比对

翻面操作(对y轴)为x=-x  旋转90度(对原点)为 x=-y y=x;

现在问题转换为判断A和B是否可以经过平移可以拼成矩形 

因为A,B拼接肯定存在公共点 所以不妨各枚举A,B上的一点Ai,Bj

将Ai,Bj平移到原点上(A,B跟着平移),然后将A、B重合的边删掉。

最后求出剩余边的上下左右4个边界 那么剩下的边必须满足处于边界上 且共计有4个点位于4角上

(因为存在顺逆时针问题,A,B都加了双向边,所以代码中判断的数目都为双倍)

并且由于切的一刀笔直的 所以之前删掉边的数目必须为2  (如果取消这个条件 即可解决切线为折线的问题)

#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<iostream>
#include<algorithm>
#include<vector>
#include<list>
#include<set>
#include<map>
#include<stack>
#include<queue>
#include<deque>
#define mem(x,y) memset(x,y,sizeof(x))
#define pb push_back
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int,int> pii;
#define mp make_pair
#define bug puts("===========");
#define zjc puts("");
const double pi=(acos(-1.0));
const double eps=1e-2;
const ll INF=1e18+10;
const ll inf=1e18+10;
const int maxn=10000+50;
const int NV=10000+50;
const int NE=1e4+100;
const int MOD=1e9+7;
/*=========================*/
struct point{
    ll x,y;
    //2个向量的叉积
    friend ll det(const point &a, const point &b){ return a.x * b.y - a.y * b.x; }
    int in()  { return ~scanf("%lld %lld", &x, &y); }
    void out(){ printf("%lld %lld\n", x, y); }
    bool operator < (const point &b) const{
        return x<b.x||(x==b.x&&y<b.y);
    }
    bool operator == (const point &b) const{
        return x==b.x&&y==b.y;
    }
};
struct line{
     point s,t;
    line(const point &s = point(), const point &t = point()): s(s), t(t) {}
    bool operator < (const line &b) const{
        return s<b.s||(s==b.s&&t<b.t);
    }
    bool operator == (const line &b) const{
        return s==b.s&&t==b.t;
    }
    bool operator != (const line &b) const {
        return !(*this==b);
    }

};
struct polygon{
    #define next(i) ((i+1)%n)
    int n;
    vector<point> p;
    polygon(int n=0): n(n){ p.resize(n); }
   void in() {
        scanf("%d",&n);
         p.clear(); point pp;
         for(int i=0;i<n;i++){
                pp.in();
                p.push_back(pp);
        }
    }
    void fan(){
        for(int i=0;i<n;i++) {
            p[i].x=-p[i].x;
        }
    }
    void ro(){
        for(int i=0;i<n;i++) {
            ll xxx=p[i].x;
            p[i].x=-p[i].y;
            p[i].y=xxx;
        }
    }
    void go(int id){
        int xx=p[id].x,yy=p[id].y;
        for(int i=0;i<n;i++) {
            p[i].x-=xx;
            p[i].y-=yy;
        }
    }
}p1,p2;
vector<line>vec,ans;
vector<point> pp;
bool check(int a,int b,polygon p1,polygon p2){
    p1.go(a); p2.go(b);
    vec.clear(); ans.clear();
    for(int i=0;i<p1.n;i++){
        vec.pb(line(p1.p[i],p1.p[(i+1)%p1.n]));
        vec.pb(line(p1.p[(i+1)%p1.n],p1.p[i]));
    }
    for(int i=0;i<p2.n;i++){
        vec.pb(line(p2.p[i],p2.p[(i+1)%p2.n]));
        vec.pb(line(p2.p[(i+1)%p2.n],p2.p[i]));
    }
    ll maxx=0,maxy=0,minx=inf,miny=inf;
    sort(vec.begin(),vec.end());
    for(int i=0;i<vec.size();i++){
        if((i==0||vec[i]!=vec[i-1])&&(i==vec.size()-1||vec[i]!=vec[i+1])){
            ans.pb(vec[i]);
            maxx=max(maxx,vec[i].s.x);
            maxx=max(maxx,vec[i].t.x);
            minx=min(minx,vec[i].s.x);
            minx=min(minx,vec[i].t.x);
            maxy=max(maxy,vec[i].s.y);
            maxy=max(maxy,vec[i].t.y);
            miny=min(miny,vec[i].s.y);
            miny=min(miny,vec[i].t.y);
        }
    }
    int cnt=0;
    for(int i=0;i<ans.size();i++){
        int flag=0;
        if(ans[i].s.x==maxx||ans[i].s.x==minx) flag++;
        if(ans[i].s.y==maxy||ans[i].s.y==miny) flag++;
        if(flag==0) return 0;
        else if(flag==2) cnt++;
        flag=0;
        if(ans[i].t.x==maxx||ans[i].t.x==minx) flag++;
        if(ans[i].t.y==maxy||ans[i].t.y==miny) flag++;
        if(flag==0) return 0;
        else if(flag==2) cnt++;
        if(ans[i].s.x!=ans[i].t.x&&ans[i].s.y!=ans[i].t.y) return 0;
    }
    return (vec.size()-ans.size()==4)&&cnt>=16;
}
bool solve(){
    for(int i=0;i<p1.n;i++)
        for(int j=0;j<p2.n;j++)
            if(check(i,j,p1,p2)) return 1;
    return 0;
}
bool go(){
    if(solve()) return 1;
    p2.ro();if(solve()) return 1;
    p2.ro();if(solve()) return 1;
    p2.ro();if(solve()) return 1;
    p2.ro();
    return 0;
}
int main()
{
    int T_T;
    scanf("%d",&T_T);
    while(T_T--){
        p1.in(); p2.in();
        if(go()) puts("YES");
        else if(p2.fan(),go()) puts("YES");
        else puts("NO");
    }
    return 0;
}



0
0

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:27469次
    • 积分:1840
    • 等级:
    • 排名:千里之外
    • 原创:167篇
    • 转载:0篇
    • 译文:0篇
    • 评论:2条