PAT 团体程序设计天梯赛 部分题目题解

L1-002. 打印沙漏

本题要求你写个程序把给定的符号打印成沙漏的形状。例如给定17个“*”,要求按下列格式打印

*****
 ***
  *
 ***
*****

所谓“沙漏形状”,是指每行输出奇数个符号;各行符号中心对齐;相邻两行符号数差2;符号数先从大到小顺序递减到1,再从小到大顺序递增;首尾符号数相等。

给定任意N个符号,不一定能正好组成一个沙漏。要求打印出的沙漏能用掉
尽可能多的符号。

模拟

#include<bits/stdc++.h>
using namespace std;
#define For(i,n) for(int i=1;i<=n;i++)
#define Fork(i,k,n) for(int i=k;i<=n;i++)
#define Rep(i,n) for(int i=0;i<n;i++)
#define ForD(i,n) for(int i=n;i;i--)
#define ForkD(i,k,n) for(int i=n;i>=k;i--)
#define RepD(i,n) for(int i=n;i>=0;i--)
#define Forp(x) for(int p=Pre[x];p;p=Next[p])
#define Forpiter(x) for(int &p=iter[x];p;p=Next[p])  
#define Lson (o<<1)
#define Rson ((o<<1)+1)
#define MEM(a) memset(a,0,sizeof(a));
#define MEMI(a) memset(a,127,sizeof(a));
#define MEMi(a) memset(a,128,sizeof(a));
#define INF (2139062143)
#define F (100000007)
#define pb push_back
#define mp make_pair 
#define fi first
#define se second
#define vi vector<int> 
#define pi pair<int,int>
#define SI(a) ((a).size())
#define Pr(kcase,ans) printf("Case #%d: %lld\n",kcase,ans);
#define PRi(a,n) For(i,n-1) cout<<a[i]<<' '; cout<<a[n]<<endl;
#define PRi2D(a,n,m) For(i,n) { \
                        For(j,m-1) cout<<a[i][j]<<' ';\
                        cout<<a[i][m]<<endl; \
                        } 
#pragma comment(linker, "/STACK:102400000,102400000")
typedef long long ll;
typedef long double ld;
typedef unsigned long long ull;
ll mul(ll a,ll b){return (a*b)%F;}
ll add(ll a,ll b){return (a+b)%F;}
ll sub(ll a,ll b){return ((a-b)%F+F)%F;}
void upd(ll &a,ll b){a=(a%F+b%F)%F;}
int read()
{
    int x=0,f=1; char ch=getchar();
    while(!isdigit(ch)) {if (ch=='-') f=-1; ch=getchar();}
    while(isdigit(ch)) { x=x*10+ch-'0'; ch=getchar();}
    return x*f;
} 
int main()
{
//  freopen("b.in","r",stdin);
//  freopen(".out","w",stdout);
    int n;
    char c;
    scanf("%d %c\n",&n,&c);
    int i,t;
    for(i=1,t=1;t+i*2+4<=n;i+=2,t+=(i*2)) ;

    for(int k=i;k>0;k-=2) {
        int p=(i-k)/2;
        For(j,p) putchar(' ');
        For(j,k) putchar(c);
        puts("");
    }   
    for(int k=3;k<=i;k+=2) {
        int p=(i-k)/2;
        For(j,p) putchar(' ');
        For(j,k) putchar(c);
        puts("");
    }   
    cout<<n-t<<endl;    

    return 0;
}

L1-006. 连续因子

一个正整数N的因子中可能存在若干连续的数字。例如630可以分解为3*5*6*7,其中5、6、7就是3个连续的数字。给定任一正整数N,要求编写程序求出最长连续因子的个数,并输出最小的连续因子序列。

#include<bits/stdc++.h>
using namespace std;
#define For(i,n) for(int i=1;i<=n;i++)
#define Fork(i,k,n) for(int i=k;i<=n;i++)
#define Rep(i,n) for(int i=0;i<n;i++)
#define ForD(i,n) for(int i=n;i;i--)
#define ForkD(i,k,n) for(int i=n;i>=k;i--)
#define RepD(i,n) for(int i=n;i>=0;i--)
#define Forp(x) for(int p=Pre[x];p;p=Next[p])
#define Forpiter(x) for(int &p=iter[x];p;p=Next[p])  
#define Lson (o<<1)
#define Rson ((o<<1)+1)
#define MEM(a) memset(a,0,sizeof(a));
#define MEMI(a) memset(a,127,sizeof(a));
#define MEMi(a) memset(a,128,sizeof(a));
#define INF (2139062143)
#define F (100000007)
#define pb push_back
#define mp make_pair 
#define fi first
#define se second
#define vi vector<int> 
#define pi pair<int,int>
#define SI(a) ((a).size())
#define Pr(kcase,ans) printf("Case #%d: %lld\n",kcase,ans);
#define PRi(a,n) For(i,n-1) cout<<a[i]<<' '; cout<<a[n]<<endl;
#define PRi2D(a,n,m) For(i,n) { \
                        For(j,m-1) cout<<a[i][j]<<' ';\
                        cout<<a[i][m]<<endl; \
                        } 
#pragma comment(linker, "/STACK:102400000,102400000")
typedef long long ll;
typedef long double ld;
typedef unsigned long long ull;
ll mul(ll a,ll b){return (a*b)%F;}
ll add(ll a,ll b){return (a+b)%F;}
ll sub(ll a,ll b){return ((a-b)%F+F)%F;}
void upd(ll &a,ll b){a=(a%F+b%F)%F;}
int read()
{
    int x=0,f=1; char ch=getchar();
    while(!isdigit(ch)) {if (ch=='-') f=-1; ch=getchar();}
    while(isdigit(ch)) { x=x*10+ch-'0'; ch=getchar();}
    return x*f;
} 
int main()
{
//  freopen("c.in","r",stdin);
//  freopen(".out","w",stdout);
    ll n=read();
    int an=0,q=0;
    for(ll i=2;i<=sqrt((double)n+0.5);i++) {
        if (n%i==0) {
            int p=0,t=n,j=i;
            while(t%j==0) {
                t/=j;
                p++;j++;
            }
            if (an<p) {
                an=p;
                q=i;
            }
        } 
    }
    if (!an) {
        an=1; q=n;
    }
    cout<<an<<endl;
    Fork(i,q,q+an-2) {
        cout<<i<<'*';
    }
    cout<<q+an-1<<endl;
    return 0;
}

L1-010. 比较大小

将输入的任意3个整数从小到大输出

#include<bits/stdc++.h>
using namespace std;
#define For(i,n) for(int i=1;i<=n;i++)
#define Fork(i,k,n) for(int i=k;i<=n;i++)
#define Rep(i,n) for(int i=0;i<n;i++)
#define ForD(i,n) for(int i=n;i;i--)
#define ForkD(i,k,n) for(int i=n;i>=k;i--)
#define RepD(i,n) for(int i=n;i>=0;i--)
#define Forp(x) for(int p=Pre[x];p;p=Next[p])
#define Forpiter(x) for(int &p=iter[x];p;p=Next[p])  
#define Lson (o<<1)
#define Rson ((o<<1)+1)
#define MEM(a) memset(a,0,sizeof(a));
#define MEMI(a) memset(a,127,sizeof(a));
#define MEMi(a) memset(a,128,sizeof(a));
#define INF (2139062143)
#define F (100000007)
#define pb push_back
#define mp make_pair 
#define fi first
#define se second
#define vi vector<int> 
#define pi pair<int,int>
#define SI(a) ((a).size())
#define Pr(kcase,ans) printf("Case #%d: %lld\n",kcase,ans);
#define PRi(a,n) For(i,n-1) cout<<a[i]<<' '; cout<<a[n]<<endl;
#define PRi2D(a,n,m) For(i,n) { \
                        For(j,m-1) cout<<a[i][j]<<' ';\
                        cout<<a[i][m]<<endl; \
                        } 
#pragma comment(linker, "/STACK:102400000,102400000")
typedef long long ll;
typedef long double ld;
typedef unsigned long long ull;
ll mul(ll a,ll b){return (a*b)%F;}
ll add(ll a,ll b){return (a+b)%F;}
ll sub(ll a,ll b){return ((a-b)%F+F)%F;}
void upd(ll &a,ll b){a=(a%F+b%F)%F;}
int read()
{
    int x=0,f=1; char ch=getchar();
    while(!isdigit(ch)) {if (ch=='-') f=-1; ch=getchar();}
    while(isdigit(ch)) { x=x*10+ch-'0'; ch=getchar();}
    return x*f;
} 
int main()
{
//  freopen("L110.in","r",stdin);
//  freopen(".out","w",stdout);
    int c[10];
    Rep(i,3) cin>>c[i];
    sort(c,c+3);
    printf("%d->%d->%d\n",c[0],c[1],c[2]);


    return 0;
}

L1-014. 简单题

在一行中输出事实:“This is a simple problem.”

puts一行

L1-018. 大笨钟

微博上有个自称“大笨钟V”的家伙,每天敲钟催促码农们爱惜身体早点睡觉。不过由于笨钟自己作息也不是很规律,所以敲钟并不定时。一般敲钟的点数是根据敲钟时间而定的,如果正好在某个整点敲,那么“当”数就等于那个整点数;如果过了整点,就敲下一个整点数。另外,虽然一天有24小时,钟却是只在后半天敲1~12下。例如在23:00敲钟,就是“当当当当当当当当当当当”,而到了23:01就会是“当当当当当当当当当当当当”。在午夜00:00到中午12:00期间(端点时间包括在内),笨钟是不敲的。
根据当前时间替大笨钟敲钟。

注意读题

#include<bits/stdc++.h>
using namespace std;
#define For(i,n) for(int i=1;i<=n;i++)
#define Fork(i,k,n) for(int i=k;i<=n;i++)
#define Rep(i,n) for(int i=0;i<n;i++)
#define ForD(i,n) for(int i=n;i;i--)
#define ForkD(i,k,n) for(int i=n;i>=k;i--)
#define RepD(i,n) for(int i=n;i>=0;i--)
#define Forp(x) for(int p=Pre[x];p;p=Next[p])
#define Forpiter(x) for(int &p=iter[x];p;p=Next[p])  
#define Lson (o<<1)
#define Rson ((o<<1)+1)
#define MEM(a) memset(a,0,sizeof(a));
#define MEMI(a) memset(a,127,sizeof(a));
#define MEMi(a) memset(a,128,sizeof(a));
#define INF (2139062143)
#define F (100000007)
#define pb push_back
#define mp make_pair 
#define fi first
#define se second
#define vi vector<int> 
#define pi pair<int,int>
#define SI(a) ((a).size())
#define Pr(kcase,ans) printf("Case #%d: %lld\n",kcase,ans);
#define PRi(a,n) For(i,n-1) cout<<a[i]<<' '; cout<<a[n]<<endl;
#define PRi2D(a,n,m) For(i,n) { \
                        For(j,m-1) cout<<a[i][j]<<' ';\
                        cout<<a[i][m]<<endl; \
                        } 
#pragma comment(linker, "/STACK:102400000,102400000")
typedef long long ll;
typedef long double ld;
typedef unsigned long long ull;
ll mul(ll a,ll b){return (a*b)%F;}
ll add(ll a,ll b){return (a+b)%F;}
ll sub(ll a,ll b){return ((a-b)%F+F)%F;}
void upd(ll &a,ll b){a=(a%F+b%F)%F;}
int read()
{
    int x=0,f=1; char ch=getchar();
    while(!isdigit(ch)) {if (ch=='-') f=-1; ch=getchar();}
    while(isdigit(ch)) { x=x*10+ch-'0'; ch=getchar();}
    return x*f;
} 
int main()
{
//  freopen("l118.in","r",stdin);
//  freopen(".out","w",stdout);
    int h,t;
    scanf("%d:%d\n",&h,&t);
    if (h<=11||(h==12&&t==0)) {
        printf("Only %02d:%02d.  Too early to Dang.",h,t);
    }
    else {
        int p=h-12;
        if (t) p++;
        For(i,p) cout<<"Dang";cout<<endl;
    }


    return 0;
}

L2-002. 链表去重

给定一个带整数键值的单链表L,本题要求你编写程序,删除那些键值的绝对值有重复的结点。即对任意键值K,只有键值或其绝对值等于K的第一个结点可以被保留。同时,所有被删除的结点必须被保存在另外一个链表中。例如:另L为21→-15→-15→-7→15,则你必须输出去重后的链表21→-15→-7、以及被删除的链表-15→15。

读题

#include<bits/stdc++.h>
using namespace std;
#define For(i,n) for(int i=1;i<=n;i++)
#define Fork(i,k,n) for(int i=k;i<=n;i++)
#define Rep(i,n) for(int i=0;i<n;i++)
#define ForD(i,n) for(int i=n;i;i--)
#define ForkD(i,k,n) for(int i=n;i>=k;i--)
#define RepD(i,n) for(int i=n;i>=0;i--)
#define Forp(x) for(int p=Pre[x];p;p=Next[p])
#define Forpiter(x) for(int &p=iter[x];p;p=Next[p])  
#define Lson (o<<1)
#define Rson ((o<<1)+1)
#define MEM(a) memset(a,0,sizeof(a));
#define MEMI(a) memset(a,127,sizeof(a));
#define MEMi(a) memset(a,128,sizeof(a));
#define INF (2139062143)
#define F (100000007)
#define pb push_back
#define mp make_pair 
#define fi first
#define se second
#define vi vector<int> 
#define pi pair<int,int>
#define SI(a) ((a).size())
#define Pr(kcase,ans) printf("Case #%d: %lld\n",kcase,ans);
#define PRi(a,n) For(i,n-1) cout<<a[i]<<' '; cout<<a[n]<<endl;
#define PRi2D(a,n,m) For(i,n) { \
                        For(j,m-1) cout<<a[i][j]<<' ';\
                        cout<<a[i][m]<<endl; \
                        } 
#pragma comment(linker, "/STACK:102400000,102400000")
typedef long long ll;
typedef long double ld;
typedef unsigned long long ull;
ll mul(ll a,ll b){return (a*b)%F;}
ll add(ll a,ll b){return (a+b)%F;}
ll sub(ll a,ll b){return ((a-b)%F+F)%F;}
void upd(ll &a,ll b){a=(a%F+b%F)%F;}
int read()
{
    int x=0,f=1; char ch=getchar();
    while(!isdigit(ch)) {if (ch=='-') f=-1; ch=getchar();}
    while(isdigit(ch)) { x=x*10+ch-'0'; ch=getchar();}
    return x*f;
} 
int n,ro;
int a[100000+10],ne[100000+10];
bool b[100000+10]={0};
vi v1,v2;
int Abs(int x){
    if (x<0) x=-x; return x;
}
int main()
{
//  freopen("L202.in","r",stdin);
//  freopen(".out","w",stdout);
    cin>>ro>>n;
    For(i,n) {
        int x,y,z;
        scanf("%d%d%d",&x,&y,&z);
        a[x]=y; ne[x]=z;
    }
    for(int i=ro;i!=-1;i=ne[i]) {
        if (!b[Abs(a[i])]) v1.pb(i),b[Abs(a[i])]=1;
        else v2.pb(i);
    }
    int sz=v1.size();
    Rep(i,sz-1) {
        int p=v1[i];
        printf("%05d %d %05d\n",p,a[p],v1[i+1]);
    }       
    if (sz) printf("%05d %d -1\n",v1[sz-1],a[v1[sz-1]]);

    sz=v2.size();
    Rep(i,sz-1) {
        int p=v2[i];
        printf("%05d %d %05d\n",p,a[p],v2[i+1]);
    }           
    if (sz) printf("%05d %d -1\n",v2[sz-1],a[v2[sz-1]]);

    return 0;
}

L2-010. 排座位

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

#include<bits/stdc++.h>
using namespace std;
#define For(i,n) for(int i=1;i<=n;i++)
#define Fork(i,k,n) for(int i=k;i<=n;i++)
#define Rep(i,n) for(int i=0;i<n;i++)
#define ForD(i,n) for(int i=n;i;i--)
#define ForkD(i,k,n) for(int i=n;i>=k;i--)
#define RepD(i,n) for(int i=n;i>=0;i--)
#define Forp(x) for(int p=Pre[x];p;p=Next[p])
#define Forpiter(x) for(int &p=iter[x];p;p=Next[p])  
#define Lson (o<<1)
#define Rson ((o<<1)+1)
#define MEM(a) memset(a,0,sizeof(a));
#define MEMI(a) memset(a,127,sizeof(a));
#define MEMi(a) memset(a,128,sizeof(a));
#define INF (2139062143)
#define F (100000007)
#define pb push_back
#define mp make_pair 
#define fi first
#define se second
#define vi vector<int> 
#define pi pair<int,int>
#define SI(a) ((a).size())
#define Pr(kcase,ans) printf("Case #%d: %lld\n",kcase,ans);
#define PRi(a,n) For(i,n-1) cout<<a[i]<<' '; cout<<a[n]<<endl;
#define PRi2D(a,n,m) For(i,n) { \
                        For(j,m-1) cout<<a[i][j]<<' ';\
                        cout<<a[i][m]<<endl; \
                        } 
#pragma comment(linker, "/STACK:102400000,102400000")
typedef long long ll;
typedef long double ld;
typedef unsigned long long ull;
ll mul(ll a,ll b){return (a*b)%F;}
ll add(ll a,ll b){return (a+b)%F;}
ll sub(ll a,ll b){return ((a-b)%F+F)%F;}
void upd(ll &a,ll b){a=(a%F+b%F)%F;}
int read()
{
    int x=0,f=1; char ch=getchar();
    while(!isdigit(ch)) {if (ch=='-') f=-1; ch=getchar();}
    while(isdigit(ch)) { x=x*10+ch-'0'; ch=getchar();}
    return x*f;
} 
#define MAXN (100+10)
class bingchaji
{
public:
    int father[MAXN],n;
    void mem(int _n)
    {
        n=_n;
        For(i,n) father[i]=i;
    }
    int getfather(int x) 
    {
        if (father[x]==x) return x;

        return father[x]=getfather(father[x]);
    }
    void unite(int x,int y)
    {
        father[x]=getfather(father[x]);
        father[y]=getfather(father[y]);
        father[father[x]]=father[father[y]];
    }
    bool same(int x,int y)
    {
        return getfather(x)==getfather(y);
    }
}S;
int f[MAXN][MAXN]={0};
int main()
{
//  freopen("L210.in","r",stdin);
//  freopen(".out","w",stdout);


    int n=read(),m=read(),k=read();
    S.mem(n);
    For(i,m) {
        int u=read(),v=read(),w=read();
        if (w==-1) f[u][v]=f[v][u]=1;
        else S.unite(u,v);
    }
    For(i,k) {
        int u=read(),v=read();
        int b1 = S.same(u,v) ,b2=f[u][v];
        if (b1&&b2) puts("OK but...");
        if (b1&&!b2) puts("No problem");
        if (!b1&&b2) puts("No way");
        if (!b1&&!b2) puts("OK");
    }   

    return 0;
}

L3-002. 堆栈

大家都知道“堆栈”是一种“先进后出”的线性结构,基本操作有“入栈”(将新元素插入栈顶)和“出栈”(将栈顶元素的值返回并从堆栈中将其删除)。现请你实现一种特殊的堆栈,它多了一种操作叫“查中值”,即返回堆栈中所有元素的中值。对于N个元素,若N是偶数,则中值定义为第N/2个最小元;若N是奇数,则中值定义为第(N+1)/2个最小元。

输入格式:

输入第一行给出正整数N(<= 105)。随后N行,每行给出一个操作指令,为下列3种指令之一:

Push key
Pop
PeekMedian
其中Push表示入栈,key是不超过105的正整数;Pop表示出栈;PeekMedian表示查中值。

输出格式:

对每个入栈指令,将key入栈,并不输出任何信息。对每个出栈或查中值的指令,在一行中打印相应的返回结果。若指令非法,就打印“Invalid”。

题解:建立2个set,一个存小于中位数的部分,一个存大于中位数的部分,可以用S.erase(S.find(x))删除某个特定元素,记得每次操作后平衡2个set的size

#include<bits/stdc++.h>
using namespace std;
#define For(i,n) for(int i=1;i<=n;i++)
#define Fork(i,k,n) for(int i=k;i<=n;i++)
#define Rep(i,n) for(int i=0;i<n;i++)
#define ForD(i,n) for(int i=n;i;i--)
#define ForkD(i,k,n) for(int i=n;i>=k;i--)
#define RepD(i,n) for(int i=n;i>=0;i--)
#define Forp(x) for(int p=Pre[x];p;p=Next[p])
#define Forpiter(x) for(int &p=iter[x];p;p=Next[p])  
#define Lson (o<<1)
#define Rson ((o<<1)+1)
#define MEM(a) memset(a,0,sizeof(a));
#define MEMI(a) memset(a,127,sizeof(a));
#define MEMi(a) memset(a,128,sizeof(a));
#define INF (2139062143)
#define F (100000007)
#define pb push_back
#define mp make_pair 
#define fi first
#define se second
#define vi vector<int> 
#define pi pair<int,int>
#define SI(a) ((a).size())
#define Pr(kcase,ans) printf("Case #%d: %lld\n",kcase,ans);
#define PRi(a,n) For(i,n-1) cout<<a[i]<<' '; cout<<a[n]<<endl;
#define PRi2D(a,n,m) For(i,n) { \
                        For(j,m-1) cout<<a[i][j]<<' ';\
                        cout<<a[i][m]<<endl; \
                        } 
#pragma comment(linker, "/STACK:102400000,102400000")
typedef long long ll;
typedef long double ld;
typedef unsigned long long ull;
ll mul(ll a,ll b){return (a*b)%F;}
ll add(ll a,ll b){return (a+b)%F;}
ll sub(ll a,ll b){return ((a-b)%F+F)%F;}
void upd(ll &a,ll b){a=(a%F+b%F)%F;}
int read()
{
    int x=0,f=1; char ch=getchar();
    while(!isdigit(ch)) {if (ch=='-') f=-1; ch=getchar();}
    while(isdigit(ch)) { x=x*10+ch-'0'; ch=getchar();}
    return x*f;
} 
#define MAXN (100000+10)
int st[MAXN],sz=0;
multiset<int> S1,S2;
multiset<int>::iterator it;
int sz1=0,sz2=0;
int mid=0;
int find_s1_max(){
    if (S1.empty()) return 0;
    it=S1.end(); it--;
    return *it; 
}
int find_s2_min(){
    if (S2.empty()) return  INF;
    it=S2.begin();
    return *it; 
}

void balance() {
    while (sz1<sz2-1) {
        int t=find_s2_min();
        S2.erase(S2.find(t));--sz2;
        S1.insert(t);++sz1;
    } 
    while (sz1>sz2) {
        int t=find_s1_max();
        S1.erase(S1.find(t));--sz1;
        S2.insert(t);++sz2;
    }
    if (sz1==sz2-1) mid=find_s2_min();
    else mid=find_s1_max();
} 
void pri(set<int> &S) {
    cout<<"s:"; 
    for(it=S.begin();it!=S.end();it++) 
    {
        cout<<*it<<' ';
    }
    cout<<endl;
}
char s[100];
int main()
{
    freopen("L302.in","r",stdin);
//  freopen(".out","w",stdout);

    int n=read();
    while(n--) {
        scanf("%s",s);
        if (s[1]=='o') {
            if (!sz) {
                puts("Invalid");
                continue;
            }
//          pri(S1);pri(S2);
            if (S1.find(st[sz])!=S1.end()) S1.erase(S1.find(st[sz])),--sz1;
            else S2.erase(S2.find(st[sz])),--sz2;
            printf("%d\n",st[sz--]); 

        } else if (s[1]=='u') {
            st[++sz]=read();
            if (st[sz]<mid) S1.insert(st[sz]),++sz1;
            else S2.insert(st[sz]),++sz2;
        } else {
            if (!sz) {
                puts("Invalid");
                continue;
            }
            printf("%d\n",mid); 
        }
        balance();
    } 


    return 0;
}

L3-006. 迎风一刀斩

刘汝佳
迎着一面矩形的大旗一刀斩下,如果你的刀够快的话,这笔直一刀可以切出两块多边形的残片。反过来说,如果有人拿着两块残片来吹牛,说这是自己迎风一刀斩落的,你能检查一下这是不是真的吗?

注意摆在你面前的两个多边形可不一定是端端正正摆好的,它们可能被平移、被旋转(逆时针90度、180度、或270度),或者被(镜像)翻面。

这里假设原始大旗的四边都与坐标轴是平行的。

输入格式:

输入第一行给出一个正整数N(<=20),随后给出N对多边形。每个多边形按下列格式给出:

k x1 y1 … xk yk

其中k(2 < k <= 10)是多边形顶点个数;(xi, yi)(0 <= xi, yi <= 108)是顶点坐标,按照顺时针或逆时针的顺序给出。

注意:题目保证没有多余顶点。即每个多边形的顶点都是不重复的,任意3个相邻顶点不共线。

输出格式:

对每一对多边形,输出”YES”或者”NO”。

分情况讨论
首先枚举旋转,枚举镜像操作,枚举起点,枚举顺/逆时针
在分为4种情况考虑:
2个全等三角形
直角梯形+三角形
2个直角梯形
五边形+三角形

#include<bits/stdc++.h>
using namespace std;
#define For(i,n) for(int i=1;i<=n;i++)
#define Fork(i,k,n) for(int i=k;i<=n;i++)
#define Rep(i,n) for(int i=0;i<n;i++)
#define ForD(i,n) for(int i=n;i;i--)
#define ForkD(i,k,n) for(int i=n;i>=k;i--)
#define RepD(i,n) for(int i=n;i>=0;i--)
#define Forp(x) for(int p=Pre[x];p;p=Next[p])
#define Forpiter(x) for(int &p=iter[x];p;p=Next[p])  
#define Lson (o<<1)
#define Rson ((o<<1)+1)
#define MEM(a) memset(a,0,sizeof(a));
#define MEMI(a) memset(a,127,sizeof(a));
#define MEMi(a) memset(a,128,sizeof(a));
#define INF (2139062143)
#define F (100000007)
#define pb push_back
#define mp make_pair 
#define fi first
#define se second
#define vi vector<int> 
#define pi pair<int,int>
#define SI(a) ((a).size())
#define Pr(kcase,ans) printf("Case #%d: %lld\n",kcase,ans);
#define PRi(a,n) For(i,n-1) cout<<a[i]<<' '; cout<<a[n]<<endl;
#define PRi2D(a,n,m) For(i,n) { \
                        For(j,m-1) cout<<a[i][j]<<' ';\
                        cout<<a[i][m]<<endl; \
                        } 
#pragma comment(linker, "/STACK:102400000,102400000")
typedef long long ll;
typedef long double ld;
typedef unsigned long long ull;
ll mul(ll a,ll b){return (a*b)%F;}
ll add(ll a,ll b){return (a+b)%F;}
ll sub(ll a,ll b){return ((a-b)%F+F)%F;}
void upd(ll &a,ll b){a=(a%F+b%F)%F;}
int read()
{
    int x=0,f=1; char ch=getchar();
    while(!isdigit(ch)) {if (ch=='-') f=-1; ch=getchar();}
    while(isdigit(ch)) { x=x*10+ch-'0'; ch=getchar();}
    return x*f;
} 
int n;

ll sqr(ll a){return a*a;}
ld sqr(ld a){return a*a;}
double sqr(double a){return a*a;}

ld PI = 3.141592653589793238462643383;
class P{
public:
    double x,y;
    P(double x=0,double y=0):x(x),y(y){}
    friend long double dis2(P A,P B){return sqr(A.x-B.x)+sqr(A.y-B.y);  }
    friend long double Dot(P A,P B) {return A.x*B.x+A.y*B.y; }
    friend long double Length(P A) {return sqrt(Dot(A,A)); }
    friend long double Angle(P A,P B) {return acos(Dot(A,B) / Length(A) / Length(B) ); }

    friend P operator- (P A,P B) { return P(A.x-B.x,A.y-B.y); }
    friend P operator+ (P A,P B) { return P(A.x+B.x,A.y+B.y); }
    friend P operator* (P A,double p) { return P(A.x*p,A.y*p); }
    friend P operator/ (P A,double p) { return P(A.x/p,A.y/p); }
    friend bool operator< (const P& a,const P& b) {return a.x<b.x||(a.x==b.x&& a.y<b.y);}

}; 
const double eps=1e-2;
int dcmp(double x) {
    if (fabs(x)<eps) return 0; else return x<0 ? -1 : 1; 
}
bool operator==(const P& a,const P& b) {
    return dcmp(a.x-b.x)==0 && dcmp(a.y-b.y) == 0;
} 

bool operator!=(const P& a,const P& b) {
    return !(a==b);
} 
typedef P V;

V Rotate(V A,double rad) {
    return V(A.x*cos(rad)-A.y*sin(rad),A.x*sin(rad)+A.y*cos(rad));
} 
// A 不是 0向量 


P read_point() {
    P a;
    scanf("%lf%lf",&a.x,&a.y);
    return a;   
} 
int k1,k2;
P A[30],B[30];
bool check1(vector<P> &poly1,vector<P> &poly2) {
    cout<<setiosflags(ios::fixed)<<setprecision(0);
    V v1=poly1[0],v2=poly2[0];
    Rep(i,3) poly1[i]=poly1[i]-v1,poly2[i]=poly2[i]-v2;
    if (poly1[1]!=poly2[1]) return 0;
    Rep(i,3) if (poly1[i]!=poly2[i]) return 0;
    if (dcmp(poly1[1].x) != 0 || dcmp(poly1[2].y) != 0) return 0;
    return 1;
}
bool check2(vector<P> &poly1,vector<P> &poly2) {
    V v1=poly1[0],v2=poly2[0];
    Rep(i,4) poly1[i]=poly1[i]-v1;
    Rep(i,3) poly2[i]=poly2[i]-v2;
    if (poly1[1]!=poly2[1]) return 0;
    if (dcmp(poly1[3].y) != 0 || dcmp(poly1[2].y-poly1[1].y) != 0 ) return 0;
    if (dcmp(poly2[1].x) != 0 || dcmp(poly2[2].y) != 0) return 0;
    if (dcmp(poly1[2].x-poly1[3].x-poly2[2].x ) != 0 ) return 0;
    return 1;
}
bool check3(vector<P> &poly1,vector<P> &poly2) {
    V v1=poly1[0],v2=poly2[0];
    Rep(i,4) poly1[i]=poly1[i]-v1;
    Rep(i,4) poly2[i]=poly2[i]-v2;
    if (poly1[1]!=poly2[1]) return 0;
    if (dcmp(poly1[3].y) != 0 || dcmp(poly1[2].y-poly1[1].y) != 0 ) return 0;
    if (dcmp(poly2[3].y) != 0 || dcmp(poly2[2].y-poly2[1].y) != 0 ) return 0;
    if (dcmp(poly1[1].x) != 0 ) return 0;
    if (dcmp(poly1[2].x-poly1[3].x-poly2[2].x +poly2[3].x ) != 0 ) return 0;
    return 1;
}
bool check4(vector<P> &poly1,vector<P> &poly2) {
    V v1=poly1[0],v2=poly2[0];
    Rep(i,5) poly1[i]=poly1[i]-v1;
    Rep(i,3) poly2[i]=poly2[i]-v2;
    if (dcmp(poly1[4].y) != 0 || dcmp(poly1[2].y-poly1[1].y) != 0 ) return 0;
    if (dcmp(poly1[1].x) != 0 || dcmp(poly1[4].x-poly1[3].x) != 0 ) return 0;
    if (dcmp(poly1[2].x-poly1[3].x)>=0 || dcmp(poly1[2].y -poly1[3].y) <=0  ) return 0;
    if (dcmp(poly2[1].x) != 0 || dcmp(poly2[2].y) != 0) return 0;
    if (dcmp(poly1[2].x-poly1[3].x+poly2[2].x) !=0 || dcmp(poly1[2].y -poly1[3].y - poly2[1].y) !=0 ) return 0;
    return 1;
}


bool checkT() {
    for(int b1=-1;b1<=1;b1+=2)
        for(int b2=-1;b2<=1;b2+=2)
            Rep(i,k1)
                Rep(j,k2) {
                    vector<P> poly1,poly2;
                    Rep(k,k1)
                        poly1.pb(A[(i+b1*k+k1)%k1]);
                    Rep(l,k2)
                        poly2.pb(B[(j+b2*l+k2)%k2]);
                    if (k1==3&&k2==3) if (check1(poly1,poly2)) return 1;
                    if (k1==4&&k2==3) if (check2(poly1,poly2)) return 1;
                    if (k1==4&&k2==4) if (check3(poly1,poly2)) return 1;
                    if (k1==5&&k2==3) if (check4(poly1,poly2)) return 1;

                }
    return 0;
}
bool check() {
    Rep(k,4) {  
        Rep(i,k1) A[i]=Rotate(A[i],PI/2);
        Rep(l,4) {
            Rep(i,k2) B[i]=Rotate(B[i],PI/2);
            if (checkT()) return 1;
        }
    }   
    Rep(i,k1) A[i].x*=-1;
    Rep(k,4) {  
        Rep(i,k1) A[i]=Rotate(A[i],PI/2);
        Rep(l,4) {
            Rep(i,k2) B[i]=Rotate(B[i],PI/2);
            if (checkT()) return 1;
        }
    }   
    Rep(i,k1) A[i].x*=-1;
    Rep(i,k2) B[i].x*=-1;
    Rep(k,4) {  
        Rep(i,k1) A[i]=Rotate(A[i],PI/2);
        Rep(l,4) {
            Rep(i,k2) B[i]=Rotate(B[i],PI/2);
            if (checkT()) return 1;
        }
    }   
    Rep(i,k1) A[i].x*=-1;
    Rep(k,4) {  
        Rep(i,k1) A[i]=Rotate(A[i],PI/2);
        Rep(l,4) {
            Rep(i,k2) B[i]=Rotate(B[i],PI/2);
            if (checkT()) return 1;
        }
    }   
    return 0;
}

int main()
{
//  freopen("L306.in","r",stdin);
//  freopen("l306.out","w",stdout);
    cin>>n;
    while(n--) {
        cin>>k1;
        Rep(i,k1) A[i]=read_point();
        cin>>k2;
        Rep(i,k2) B[i]=read_point();
        if (k1<k2) {
            Rep(i,k2) swap(A[i],B[i]);
            swap(k1,k2);
        }
        if(check()) puts("YES"); else puts("NO");
    }


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值