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

原创 2016年05月30日 16:17:49

题目链接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;
}



版权声明:本文为博主原创文章,未经博主允许不得转载。

相关文章推荐

Codeforces Round 718C(维护矩阵的线段树)

C. Sasha and Array time limit per test 5 seconds memory limit per test 256 megabytes inpu...
  • Yasola
  • Yasola
  • 2016年09月25日 15:51
  • 682

hdu 5204 Rikka with sequence(BestCoder Round #37)

Rikka with sequence                                                        Time Limit: 2000/1000 MS...
  • caduca
  • caduca
  • 2015年04月13日 15:53
  • 3825

天梯赛练习集 L3-006 迎风一刀斩

迎风一刀斩看到这题的时候一脸懵逼。。。后来才发现原来旋转角度只有90度、180度、或270度。。。不过还是查了一下题解。。。其实只有四种情况,只要会画就差不多会写了。解释一下代码。。。 check(...

团体程序设计天梯赛L3-008——喊山(bfs)

喊山,是人双手围在嘴边成喇叭状,对着远方高山发出“喂—喂喂—喂喂喂……”的呼唤。呼唤声通过空气的传递,回荡于深谷之间,传送到人们耳中,发出约定俗成的“讯号”,达到声讯传递交流的目的。原来它是彝族先民用...

团体程序设计天梯赛——排座位(dfs)

布置宴席最微妙的事情,就是给前来参宴的各位宾客安排座位。无论如何,总不能把两个死对头排到同一张宴会桌旁!这个艰巨任务现在就交给你,对任何一对客人,请编写程序告诉主人他们是否能被安排同席。输入格式:输入...

团体程序设计天梯赛——红色警报(dfs)

战争中保持各个城市间的连通性非常重要。本题要求你编写一个报警程序,当失去一个城市导致国家被分裂为多个无法连通的区域时,就发出红色警报。注意:若该国本来就不完全连通,是分裂的k个区域,而失去一个城市并不...

团体程序设计天梯赛——玩转二叉树(遍历构造二叉树)

给定一棵二叉树的中序遍历和前序遍历,请你先将树做个镜面反转,再输出反转后的层序遍历的序列。所谓镜面反转,是指将所有非叶结点的左右孩子对换。这里假设键值都是互不相等的正整数。输入格式:输入第一行给出一个...

一刀斩绿色免安装杀毒软件

  • 2009年11月20日 17:11
  • 378KB
  • 下载

L2-012. 关于堆的判断-PAT团体程序设计天梯赛GPLT

L2-012. 关于堆的判断 将一系列给定数字顺序插入一个初始为空的小顶堆H[]。随后判断一系列相关命题是否为真。命题分下列几种: “x is the root”:x是根结点; “x...
  • liuchuo
  • liuchuo
  • 2016年09月09日 17:02
  • 217
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:程序设计天梯赛——迎风一刀斩
举报原因:
原因补充:

(最多只允许输入30个字)