POJ 3449 Geometric Shapes 判断多边形相交

题意不难理解,给出多个多边形,输出多边形间的相交情况(嵌套不算相交),思路也很容易想到。枚举每一个图形再枚举每一条边

恶心在输入输出,不过还好有sscanf(),不懂可以查看cplusplus网站

根据正方形对角的两顶点求另外两个顶点公式:

x2 = (x1+x3-y3+y1)/2; y2 = (x3-x1+y1+y3)/2;

x4= (x1+x3+y3-y1)/2; y4 = (-x3+x1+y1+y3)/2;

还有很多细节要处理

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <map>
using namespace std;

const double eps = 1e-8;
const double PI = acos(-1.0);

int sgn(double x)
{
    if(fabs(x) < eps) return 0;
    return x < 0 ? -1:1;
}

struct Point
{
    double x,y;
    Point() {}
    Point(double _x,double _y)
    {
        x = _x,y = _y;
    }
    Point operator -(const Point &b)const
    {
        return Point(x - b.x,y - b.y);
    }
    //叉积
    double operator ^(const Point &b)const
    {
        return x*b.y - y*b.x;
    }
    //点积
    double operator *(const Point &b)const
    {
        return x*b.x + y*b.y;
    }
};

struct Line
{
    Point p,q;
    Line() {};
    Line(Point _p,Point _q)
    {
        p = _p,q = _q;
    }
};

//*判断线段相交
bool inter(Line l1,Line l2)
{
    return
        max(l1.p.x,l1.q.x) >= min(l2.p.x,l2.q.x) &&
        max(l2.p.x,l2.q.x) >= min(l1.p.x,l1.q.x) &&
        max(l1.p.y,l1.q.y) >= min(l2.p.y,l2.q.y) &&
        max(l2.p.y,l2.q.y) >= min(l1.p.y,l1.q.y) &&
        sgn((l2.p-l1.q)^(l1.p-l1.q))*sgn((l2.q-l1.q)^(l1.p-l1.q)) <= 0 &&
        sgn((l1.p-l2.q)^(l2.p-l2.q))*sgn((l1.q-l2.q)^(l2.p-l2.q)) <= 0;
}

const int maxn=30;

struct Shape
{
    char id;
    int nump;
    Point p[maxn];
} shp[maxn];

bool cmp(Shape a,Shape b)
{
    return a.id<b.id;
}

char str[20];
int num[maxn];
char inters[maxn][maxn];
map<string,int>mp;

int main()
{
//    freopen("in.txt","r",stdin);
    mp["square"]=2;
    mp["line"]=2;
    mp["triangle"]=3;
    mp["rectangle"]=3;
    int cnt=0;
    while(scanf("%s",str))
    {
        if(strcmp(str,".")==0) break;
        if(strcmp(str,"-")!=0)
        {
            shp[cnt].id=str[0];
            char str_sh[20];
            scanf("%s",str_sh);
            int n;
            if(mp.count(str_sh)) n=mp[str_sh];
            else scanf("%d",&n);
            shp[cnt].nump=0;
            for(int i=0; i<n; i++)
            {
                scanf("%s",str);
                int x,y;
                sscanf(str,"%*c%d%*c%d",&x,&y);
                shp[cnt].p[shp[cnt].nump++]=Point(x,y);
            }
            if(strcmp(str_sh,"rectangle")==0)
            {
                Point p1=shp[cnt].p[0];
                Point p2=shp[cnt].p[1];
                Point p3=shp[cnt].p[2];
                shp[cnt].p[shp[cnt].nump++]=Point(p1.x+p3.x-p2.x,p1.y+p3.y-p2.y);
            }
            if(strcmp(str_sh,"square")==0)
            {
                Point p1=shp[cnt].p[0];
                Point p3=shp[cnt].p[1];
                shp[cnt].p[shp[cnt].nump++]=Point((p1.x+p3.x-p3.y+p1.y)/2,(p3.x-p1.x+p1.y+p3.y)/2);
                shp[cnt].p[shp[cnt].nump++]=Point((p1.x+p3.x+p3.y-p1.y)/2,(-p3.x+p1.x+p1.y+p3.y)/2);
                swap(shp[cnt].p[1],shp[cnt].p[2]);
            }
            cnt++;
            continue;
        }
        sort(shp,shp+cnt,cmp);
        memset(num,0,sizeof(num));
        for(int i=0; i<cnt; i++)
        {
            for(int j=i+1; j<cnt; j++)
            {
                bool flag=false;
                int num1=shp[i].nump;
                int num2=shp[j].nump;
                for(int k1=0; k1<num1 && !flag; k1++)
                {
                    for(int k2=0; k2<num2 && !flag; k2++)
                    {
                        if(inter(Line(shp[i].p[k1],shp[i].p[(k1+1)%num1]),Line(shp[j].p[k2],shp[j].p[(k2+1)%num2])))
                        {
                            inters[i][num[i]++]=shp[j].id;
                            inters[j][num[j]++]=shp[i].id;
                            flag=true;
                        }
                    }
                }
            }
        }
        for(int i=0; i<cnt; i++)
        {
            printf("%c ",shp[i].id);
            if(num[i]==0)
                printf("has no intersections\n");
            else if(num[i]==1)
                printf("intersects with %c\n",inters[i][0]);
            else if(num[i]==2)
                printf("intersects with %c and %c\n",inters[i][0],inters[i][1]);
            else
            {
                printf("intersects with ");
                for(int j=0;j<num[i]-1;j++)
                    printf("%c, ",inters[i][j]);
                printf("and %c\n",inters[i][num[i]-1]);
            }
        }
        cnt=0;
        puts("");
    }
    return 0;
}
时间: 2024-12-29 06:49:18

POJ 3449 Geometric Shapes 判断多边形相交的相关文章

TOJ 2560 Geometric Shapes(判断多边形是否相交)

描述 While creating a customer logo, ACM uses graphical utilities to draw a picture that can later be cut into special fluorescent materials. To ensure proper processing, the shapes in the picture cannot intersect. However, some logos contain such inte

简单几何(线段相交)+模拟 POJ 3449 Geometric Shapes

题目传送门 题意:给了若干个图形,问每个图形与哪些图形相交 分析:题目说白了就是处理出每个图形的线段,然后判断是否相交.但是读入输出巨恶心,就是个模拟题加上线段相交的判断,我第一次WA不知道输出要按字母序输出,第二次WA是因为忘记多边形的最后一条线段,还好找到了,没有坚持的话就不会AC了. /************************************************ * Author :Running_Time * Created Time :2015/10/31 星期六

POJ 3449 Geometric Shapes (求正方形的另外两点)

Geometric Shapes Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 1470   Accepted: 622 Description While creating a customer logo, ACM uses graphical utilities to draw a picture that can later be cut into special fluorescent materials. To

POJ 3449 Geometric Shapes --计算几何,线段相交

题意: 给一些多边形或线段,输出与每一个多边形或线段的有哪一些多边形或线段. 解法: 想法不难,直接暴力将所有的图形处理成线段,然后暴力枚举,相交就加入其vector就行了.主要是代码有点麻烦,一步一步来吧. 还有收集了一个线段旋转的函数. Vector Rotate(Point P,Vector A,double rad){ //以P为基准点把向量A旋转rad return Vector(P.x+A.x*cos(rad)-A.y*sin(rad),P.y+A.x*sin(rad)+A.y*co

POJ 3449 Geometric Shapes

判断两个多边形是否相交,只需判断边是否有相交. 编码量有点大,不过思路挺简单的. #include<cstdio> #include<cstring> #include<vector> #include<cmath> #include<string> #include<queue> #include<list> #include<algorithm> #include<iostream> using

POJ 1269 Intersecting Lines(判断直线相交)

题目地址:POJ 1269 直接套模板就可以了...实在不想自己写模板了...写的又臭又长....不过这题需要注意的是要先判断是否有直线垂直X轴的情况. 代码如下: #include <iostream> #include <cstdio> #include <string> #include <cstring> #include <stdlib.h> #include <math.h> #include <ctype.h>

poj Pick-up sticks(判断线段相交)

Pick-up sticks Time Limit: 3000MS   Memory Limit: 65536K Total Submissions: 11537   Accepted: 4337 Description Stan has n sticks of various length. He throws them one at a time on the floor in a random way. After finishing throwing, Stan tries to fin

POJ 2653 Pick-up sticks (判断线段相交)

Pick-up sticks Time Limit: 3000MS   Memory Limit: 65536K Total Submissions: 10330   Accepted: 3833 Description Stan has n sticks of various length. He throws them one at a time on the floor in a random way. After finishing throwing, Stan tries to fin

[poj] 1066 Treasure Hunt || 判断直线相交

原题 在金字塔内有一个宝藏p(x,y),现在要取出这个宝藏. 在金字塔内有许多墙,为了进入宝藏所在的房间必须把墙炸开,但是炸墙只能炸每个房间墙的中点. 求将宝藏运出城堡所需要的最小炸墙数. 判断点和直线相交. 枚举每道墙的两个端点和p的连线这条线段和墙的交点的次数最小值即为需要炸墙的最小次数. [注意当墙数为零时输出1:] #include<cstdio> #include<algorithm> #define N 33 using namespace std; int ans=0