hrbust 1382 Split the Points【判断正方形+判断矩形+极角排序】

来源:互联网 发布:补水眼霜 知乎 编辑:程序博客网 时间:2024/05/16 04:36

Split the Points

Time Limit: 1000 MS

Memory Limit: 65536 K

 

Total Submit: 26(8 users)

Total Accepted: 10(7 users)

Rating: 

Special Judge: No

 

Description

There are eight distinct points on the plane.

Leyni wonders if he can split the points into two sets each containing four points so that the points from one of the sets form a square and the others form a rectangle.

Help him solve this problem.

Input

There are multiple test cases. The first line of input is an integer T indicating the number of test cases. Then T test cases follow.

For each test case:

Line 1..8. Each line contains two integer xiyi(-104 ≤ xi, yi ≤ 104) indicating the coordinate of a point.

Output

For each test case:

Line 1. Output "YES" if Leyni can split the points as he desires, otherwise output "NO".

Sample Input

3

0 0

10 11

10 0

0 11

1 1

2 2

2 1

1 2

0 0

1 1

2 2

3 3

4 4

5 5

6 6

7 7

0 0

4 4

4 0

0 4

1 2

2 3

3 2

2 1

Sample Output

YES

NO

YES

Source

哈理工2012春季校赛 - 现场赛(热身)

Author

齐达拉图@HRBUST

 

题目大意:


一共t组数据,对于每组数据给出8个点,我们的任务是将这8个点分成两组,一组包含四个点,第一组的四个点要求组成一个正方形,第二个组的四个点要求组成一个矩形,问是否能够分成这样的两组。


思路:


1、首先这里分析一下时限问题,一共八个点,我们直接暴力找一个正方形的话,是需要8*8*8*8的复杂度进行枚举,然后再进行各种操作,也并不是很高,所以我们这里就不需要技巧优化分组问题了,直接先找到一个正方形之后判断剩下四个点能否组成矩形即可。


2、正方形的判断:枚举出4个点之后,求出其能够组合出来的六条边的边长,然后进行排序,得到升序的一个数组dis【】,如果dis【0-3】相等。dis【4-5】也相等,并且dis【0】*dis【0】*2==dis【5】*dis【5】,那么就能够判断这个四边形一定是正方形。(满足四条临边相等,并且满足有一个直角)


3、然后剩下四个点,我们要判断他是不是一个矩形,我们先进行一次极角排序,得到一个有序的四个点,而且我们知道,排序结束的点,p0,p2是对顶角。p1,p3是对顶角,我们用向量判断对边平行,然后一条临边垂直即可。(平行四边形的基础上加一个直角)。



AC代码:


#include<stdio.h>#include<string.h>#include<algorithm>using namespace std;struct point{    int x,y;}p[10];int x[10];int y[10];int vis[10];int cross(point a, point b, point c){    return (b.x-a.x)*(c.y-a.y)-(c.x-a.x)*(b.y-a.y);}int dis(point a){    return (a.x-p[0].x)*(a.x-p[0].x)+(a.y-p[0].y)*(a.y-p[0].y);}int cmp(point a, point b)//极角排序、{    if(cross(p[0], a, b) > 0||(cross(p[0], a, b)==0&&dis(a) < dis(b)))        return 1;    return 0;}int Slove(int one,int two,int three,int four)//判断矩形{    vis[one]=1;vis[two]=1;vis[three]=1;vis[four]=1;    int cont=0;    for(int i=0;i<8;i++)    {        if(vis[i]==0)        {            p[cont].x=x[i];            p[cont++].y=y[i];        }    }    sort(p,p+cont,cmp);    if(p[0].x-p[1].x==p[3].x-p[2].x&&p[0].y-p[1].y==p[3].y-p[2].y)    {        if(p[2].x-p[1].x==p[3].x-p[0].x&&p[2].y-p[1].y==p[3].y-p[0].y)        {            if((p[1].x-p[2].x)*(p[2].x-p[3].x)+(p[1].y-p[2].y)*(p[2].y-p[3].y)==0)            {                return 1;            }        }    }    return 0;}int main(){    int t;    scanf("%d",&t);    while(t--)    {        for(int i=0;i<8;i++)        {            scanf("%d%d",&x[i],&y[i]);        }        int flag=0;        for(int i=0;i<8;i++)        {            for(int j=i+1;j<8;j++)            {                for(int k=j+1;k<8;k++)                {                    for(int l=k+1;l<8;l++)//暴力枚举4个点出来                    {                        memset(vis,0,sizeof(vis));                        p[0].x=x[i];p[0].y=y[i];                        p[1].x=x[j];p[1].y=y[j];                        p[2].x=x[k];p[2].y=y[k];                        p[3].x=x[l];p[3].y=y[l];                        long long int dis[10];                        int cont=0;                        for(int z=0;z<4;z++)                        {                            for(int zz=z+1;zz<4;zz++)                            {                                dis[cont++]=(p[z].x-p[zz].x)*(p[z].x-p[zz].x)+(p[z].y-p[zz].y)*(p[z].y-p[zz].y);                            }                        }                        sort(dis,dis+cont);                        if(dis[0]==dis[1]&&dis[1]==dis[2]&&dis[2]==dis[3]&&dis[4]==dis[5]&&dis[0]*2==dis[5])//先判断是不是正方形                        {                            int tt=Slove(i,j,k,l);//然后判断剩下的四个点能否组成矩形                            if(tt==1)flag=1;                        }                    }                }            }        }        if(flag==1)printf("YES\n");        else printf("NO\n");    }}/*5010000 10000-10000 1000010000 -10000-10000 -100001 12 23 34 410000 10000-10000 1000010000 -10000-10000 -100009999 9999-9999 99999999 -9999-9999 -99990 20 01 21 04 24 010 210 010000 10000-10000 1000010000 -10000-10000 -10000-1 00 01 00 1*/







0 0
原创粉丝点击