poj3349——多边形相交

题目链接:poj.org/problem?id=3449

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 intersecting shapes. It is necessary to detect them and decide how to change the picture.

Given a set of geometric shapes, you are to determine all of their intersections. Only outlines are considered, if a shape is completely inside another one, it is not counted as an intersection.

 

 

Input

Input contains several pictures. Each picture describes at most 26 shapes, each specified on a separate line. The line begins with an uppercase letter that uniquely identifies the shape inside the corresponding picture. Then there is a kind of the shape and two or more points, everything separated by at least one space. Possible shape kinds are:

• square: Followed by two distinct points giving the opposite corners of the square.
• rectangle: Three points are given, there will always be a right angle between the lines connecting the first point with the second and the second with the third.
• line: Specifies a line segment, two distinct end points are given.
• triangle: Three points are given, they are guaranteed not to be co-linear.
• polygon: Followed by an integer number N (3 ≤ N ≤ 20) and N points specifying vertices of the polygon in either clockwise or anti-clockwise order. The polygon will never intersect itself and its sides will have non-zero length.

All points are always given as two integer coordinates X and Y separated with a comma and enclosed in parentheses. You may assume that |X|, |Y | ≤ 10000.

The picture description is terminated by a line containing a single dash (“-”). After the last picture, there is a line with one dot (“.”).

Output

For each picture, output one line for each of the shapes, sorted alphabetically by its identifier (X). The line must be one of the following:

• “X has no intersections”, if X does not intersect with any other shapes.
• “X intersects with A”, if X intersects with exactly 1 other shape.
• “X intersects with A and B”, if X intersects with exactly 2 other shapes.
• “X intersects with A, B, . . ., and Z”, if X intersects with more than 2 other shapes.

Please note that there is an additional comma for more than two intersections. A, B, etc. are all intersecting shapes, sorted alphabetically.

Print one empty line after each picture, including the last one.

Sample Input

A square (1,2) (3,2)
F line (1,3) (4,4)
W triangle (3,5) (5,5) (4,3)
X triangle (7,2) (7,4) (5,3)
S polygon 6 (9,3) (10,3) (10,4) (8,4) (8,1) (10,2)
B rectangle (3,3) (7,5) (8,3)
-
B square (1,1) (2,2)
A square (3,3) (4,4)
-
.

Sample Output

A has no intersections
B intersects with S, W, and X
F intersects with W
S intersects with B
W intersects with B and F
X intersects with B

A has no intersections
B has no intersections

题目翻译:

在创建客户徽标时,acm使用图形实用程序绘制一张图片,稍后可以将其剪切为特殊的荧光材料。

为确保正确处理,图片中的形状不能相交。但是,有些徽标包含这样的相交形状。有必要检测它们并决定如何改变图片。              给定一组几何图形,要确定它们的所有交点。

只考虑轮廓,如果一个形状完全位于另一个形状内,则不将其计算为交点。              

输入              

输入包含多个图片。

每张图片最多描述26个形状,每一个都在单独的行上指定。该行以一个大写字母开头,该字母唯一标识对应图片中的形状。然后是一种形状和两个或多个点,每一个点至少被一个空间隔开。

可能的形状类型有:              

•正方形:后面是两个不同的点,表示正方形的对角。              

•矩形:给定三个点,连接第一个点和第二个点的直线之间始终存在直角,第二个点和第三个点的直线之间始终存在直角。         

•直线:指定直线段,给出两个不同的端点。              

•三角形:给出三个点,保证它们不是共线的。              

•多边形:后跟整数n(3≤n≤20)和n个点,以顺时针或逆时针顺序指定多边形的顶点。多边形永远不会与自身相交,其边的长度也不会为零。              

所有点总是以两个整数坐标x和y给出,用逗号分隔,并用括号括起来。你可以假设x,y≤10000。              

图片描述以包含一个短划线(“-”)的行结尾。在最后一张图片之后,有一行有一个点(“.”)。              

输出             

对于每张图片,为每个形状输出一行,按其标识符(x)按字母顺序排序。

该行必须是以下行之一:              

•“x没有交点”,如果x没有与任何其他形状相交。              

•“X与A相交”,如果X与另一个形状正好相交。              

•“X与A和B相交”,如果X正好与另外两个形状相交。            

 •“x与a,b,相交。..,和Z“,如果X与其他两个以上的形状相交。              

请注意,对于两个以上的交叉点,还有一个额外的逗号。

A、B等都是相交的形状,按字母顺序排列。              

在每张图片后打印一个空行,包括最后一张。              

样本输入              

正方形(1,2)(3,2)              

F线(1,3)(4,4)              

W三角形(3,5)(5,5)(4,3)            

 x三角形(7,2)(7,4)(5,3)              

s多边形6(9,3)(10,3)(10,4)(8,4)(8,1)(10,2)              

B矩形(3,3)(7,5)(8,3)            

 -              

正方形(1,1)(2,2)              

正方形(3,3)(4,4)              

-              

.              

样本输出            

 A没有交叉点              

B与S、W和X相交            

 F与W相交            

 S与B相交              

W与B和F相交              

X与B相交              

A没有交叉点              

B没有交叉点 

 

题意很好理解,就是输入和输出处理有点恶心。

判断多边形相交就是分别判断各个边是否相交。

#include<iostream>
#include<cmath>
#include<cstring>
#include<cstdio>
#include<algorithm>
using namespace std;
struct Point{
    double x, y;
    Point(double x = 0, double y = 0):x(x),y(y){}
};
const double eps = 1e-6;
typedef Point Vector;
Vector operator - (Point A, Point B){
    return Vector(A.x-B.x, A.y-B.y);
}
int sgn(double x){
    if(fabs(x) < eps)
        return 0;
    if(x < 0)
        return -1;
    return 1;
}
double Cross(Vector A, Vector B){
    return A.x*B.y-A.y*B.x;
}
double Dot(Vector A, Vector B){
    return A.x*B.x + A.y*B.y;
}
struct Line{//直线定义
    Point s, e;
    Line(Point s, Point e):s(s), e(e) {}
};
bool SegmentProperIntersection(Line l1,Line l2)
{
    return
    max(l1.s.x,l1.e.x) >= min(l2.s.x,l2.e.x) &&
    max(l2.s.x,l2.e.x) >= min(l1.s.x,l1.e.x) &&
    max(l1.s.y,l1.e.y) >= min(l2.s.y,l2.e.y) &&
    max(l2.s.y,l2.e.y) >= min(l1.s.y,l1.e.y) &&
    sgn(Cross((l2.s-l1.e),(l1.s-l1.e)))*sgn(Cross((l2.e-l1.e),(l1.s-l1.e))) <= 0 &&
    sgn(Cross((l1.s-l2.e),(l2.s-l2.e)))*sgn(Cross((l1.e-l2.e),(l2.s-l2.e))) <= 0;
}
struct Style{
	char ss; 
	int num; 
	Point p[25]; 
}S[30];
int visited[30];
bool cmp(Style A,Style B){
	return A.ss<B.ss;
}
bool judge(Style a,Style b){
	for(int i=0;i<a.num;i++)
		for(int j=0;j<b.num;j++)
			if(SegmentProperIntersection(Line(a.p[i],a.p[(i+1)%a.num]),Line(b.p[j],b.p[(j+1)%b.num])))
				return true;
	return false;
}
int main(){
	string s;
	while(cin>>s){
		int cnt=0;
		if(s[0]=='.') break;
		S[cnt].ss=s[0];
		cin>>s;
		char ch;
		if(s[0]=='l'){
			S[cnt].num=2;
			for(int i=0;i<S[cnt].num;i++){
				cin>>ch;
				scanf("%lf",&S[cnt].p[i].x);
				cin>>ch;
				scanf("%lf",&S[cnt].p[i].y);
				cin>>ch;
			}
			cnt++;
		}
		else if(s[0]=='s'){
			S[cnt].num=4;
			cin>>ch;
			scanf("%lf",&S[cnt].p[0].x);
			cin>>ch;
			scanf("%lf",&S[cnt].p[0].y);
			cin>>ch;
			
			cin>>ch;
			scanf("%lf",&S[cnt].p[2].x);
			cin>>ch;
			scanf("%lf",&S[cnt].p[2].y);
			cin>>ch;
			
			S[cnt].p[1].x=((S[cnt].p[0].x+S[cnt].p[2].x)+(S[cnt].p[2].y-S[cnt].p[0].y))/2;
			S[cnt].p[1].y=((S[cnt].p[0].y+S[cnt].p[2].y)+(S[cnt].p[0].x-S[cnt].p[2].x))/2;
            S[cnt].p[3].x=((S[cnt].p[0].x+S[cnt].p[2].x)-(S[cnt].p[2].y-S[cnt].p[0].y))/2;
            S[cnt].p[3].y=((S[cnt].p[0].y+S[cnt].p[2].y)-(S[cnt].p[0].x-S[cnt].p[2].x))/2;
			cnt++;
		}
		else if(s[0]=='r'){
			S[cnt].num=4;
			for(int i=0;i<3;i++){
				cin>>ch;
				scanf("%lf",&S[cnt].p[i].x);
				cin>>ch;
				scanf("%lf",&S[cnt].p[i].y);
				cin>>ch;
			}
			S[cnt].p[3].x=S[cnt].p[2].x+(S[cnt].p[0].x-S[cnt].p[1].x);
            S[cnt].p[3].y=S[cnt].p[2].y+(S[cnt].p[0].y-S[cnt].p[1].y);
			cnt++;
		}	
		else if(s[0]=='t'){
			S[cnt].num=3;
			for(int i=0;i<S[cnt].num;i++){
				cin>>ch;
				scanf("%lf",&S[cnt].p[i].x);
				cin>>ch;
				scanf("%lf",&S[cnt].p[i].y);
				cin>>ch;
			}
			cnt++;
		}
		else if(s[0]=='p'){
			int n;
			scanf("%d",&n);
			S[cnt].num=n;
			for(int i=0;i<n;i++){
				cin>>ch;
				scanf("%lf",&S[cnt].p[i].x);
				cin>>ch;
				scanf("%lf",&S[cnt].p[i].y);
				cin>>ch;
			}
			cnt++;
		}
		while(cin>>s){
			if(s[0]=='-') break;
			S[cnt].ss=s[0];
			cin>>s;
			char ch;
			if(s[0]=='l'){
				
				S[cnt].num=2;
				for(int i=0;i<S[cnt].num;i++){
					cin>>ch;
					scanf("%lf",&S[cnt].p[i].x);
					cin>>ch;
					scanf("%lf",&S[cnt].p[i].y);
					cin>>ch;
				}
				cnt++;
			}
			else if(s[0]=='s'){
				S[cnt].num=4;
				cin>>ch;
				scanf("%lf",&S[cnt].p[0].x);
				cin>>ch;
				scanf("%lf",&S[cnt].p[0].y);
				cin>>ch;
			
				cin>>ch;
				scanf("%lf",&S[cnt].p[2].x);
				cin>>ch;
				scanf("%lf",&S[cnt].p[2].y);
				cin>>ch;
			
				S[cnt].p[1].x=((S[cnt].p[0].x+S[cnt].p[2].x)+(S[cnt].p[2].y-S[cnt].p[0].y))/2;
				S[cnt].p[1].y=((S[cnt].p[0].y+S[cnt].p[2].y)+(S[cnt].p[0].x-S[cnt].p[2].x))/2;
            	S[cnt].p[3].x=((S[cnt].p[0].x+S[cnt].p[2].x)-(S[cnt].p[2].y-S[cnt].p[0].y))/2;
            	S[cnt].p[3].y=((S[cnt].p[0].y+S[cnt].p[2].y)-(S[cnt].p[0].x-S[cnt].p[2].x))/2;
				cnt++;
			}
			else if(s[0]=='r'){
				S[cnt].num=4;
				for(int i=0;i<3;i++){
					cin>>ch;
					scanf("%lf",&S[cnt].p[i].x);
					cin>>ch;
					scanf("%lf",&S[cnt].p[i].y);
					cin>>ch;
				}
				S[cnt].p[3].x=S[cnt].p[2].x+(S[cnt].p[0].x-S[cnt].p[1].x);
            	S[cnt].p[3].y=S[cnt].p[2].y+(S[cnt].p[0].y-S[cnt].p[1].y);
				cnt++;
			}	
			else if(s[0]=='t'){
				S[cnt].num=3;
				for(int i=0;i<S[cnt].num;i++){
					cin>>ch;
					scanf("%lf",&S[cnt].p[i].x);
					cin>>ch;
					scanf("%lf",&S[cnt].p[i].y);
					cin>>ch;
				}
				cnt++;
			}
			else if(s[0]=='p'){
				int n;
				scanf("%d",&n);
				S[cnt].num=n;
				for(int i=0;i<n;i++){
					cin>>ch;
					scanf("%lf",&S[cnt].p[i].x);
					cin>>ch;
					scanf("%lf",&S[cnt].p[i].y);
					cin>>ch;
				}
				cnt++;
			}
		}
		sort(S,S+cnt,cmp);
		for(int i=0;i<cnt;i++){
			cout<<S[i].ss<<" ";
			memset(visited,0,sizeof(visited)); 
			int ans=0;
			for(int j=0;j<cnt;j++){
				if(i!=j){
					if(judge(S[i],S[j])){
						ans++;
						visited[j]=1;
					}
				}
			}
			if(!ans) printf("has no intersections\n");
			else if(ans==1)
            {
                printf("intersects with ");
                for(int j=0;j<cnt;j++){
                	if(visited[j])
                	{
                    	cout<<S[j].ss<<endl;
                    	break;
                	}
            	}
            }
            else if(ans==2){
            	printf("intersects with ");
            	for(int j=0;j<cnt;j++){
            		if(visited[j]){
            			if(ans==2) cout<<S[j].ss<<" ";
            			if(ans==1) cout<<"and "<<S[j].ss<<endl;
            			ans--;
					}
				}
			}
			else{
				printf("intersects with ");
            	for(int j=0;j<cnt;j++){
            		if(visited[j]){
            			if(ans>=2) cout<<S[j].ss<<", ";
            			if(ans==1) cout<<"and "<<S[j].ss<<endl;
            			ans--;
					}
				}
			}
		}
		printf("\n");
	}
	return 0;
}

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值