BUPT final C题: 线段相交 -计算几何

C.Segments Time Limit: 1000MS Memory Limit: 65536K Description There are some segments on the plane, we assume there 4 possible position concepts for every 2 segments: no common point, countless common points, one common point and the point is also the endpoint of either segment, one common point but the point is not the endpoint of either segment. Input The first line of the input is an integer T, which represents that there are T test cases. An integer n indicating the number of segments n line follows, 4 integers per line, x1, y1, x2, y2, representing the coordinates of the endpoints of both segments .(1<=n<=100) Output For each test case, please output 4 line, 1 integer per line For the first line, please output the number of pairs of segments that have no common point For the second line, please output the number of pairs of segments that have countless common point For the third line, please output the number of pairs of segments that have 1 common point and the point is also the endpoint of either segment For the fourth line, please output the number of pairs of segments that have 1 common point and the point is not the endpoint. After each case output a blank line include the last case。 Sample Input 2 3 -1 0 1 0 0 -1 0 1 -1 2 1 2 3 1 0 3 0 2 0 4 0 4 0 5 0 Sample Output 2 0 0 1 1 1 1 0 

 

解题报告:

这是一个简单计算几何题,主要考虑的是线段相交的问题,

主要难点是:题目中提到很多种情况,有4种情况考虑,考虑起问题起来要全面。

一般情况下我们只考虑两条线段是否相交,但是没有仔细考虑过这4种情况。

下面是代码,加了些注释,

注意:题目的有一个附加条件是线段的两个端点不会重合

#include <iostream> using namespace std; struct segment { int x1, y1, x2, y2; }Seg[105]; int N; int result[4]; //向量1(x1, y1)和向量2(x2, y2)叉乘 int mulplux(int x1, int y1, int x2, int y2) { return x1 * y2 - x2* y1; } //判断点p(xp,yp)是否在线段(1->2)上 bool online(int x1, int y1,int x2, int y2, int xp, int yp){ if(x1==x2) return yp>min(y1,y2)&&yp<max(y1,y2); if(y1==y2) return xp>min(x1,x2)&&xp<max(x1,x2); return yp>min(y1,y2)&&yp<max(y1,y2)&&xp>min(x1,x2)&&xp<max(x1,x2); } int dlcmp(int x){ return x < 0 ? -1: x > 0 ; } ////题目保证线段的两个端点不会重合 int panduan(segment& a, segment& b) { if(min(a.x1, a.x2) > max(b.x1, b.x2) || max(a.x1, a.x2) < min(b.x1, b.x2) || min(a.y1, a.y2) > max(b.y1, b.y2) || max(a.y1, a.y2) < min(b.y1, b.y2)) return 0; int d1 = mulplux(a.x2-a.x1, a.y2- a.y1, b.x1 - a.x1, b.y1- a.y1); int d2 = mulplux(a.x2-a.x1, a.y2- a.y1, b.x2 - a.x1, b.y2- a.y1); int d3 = mulplux(b.x2-b.x1, b.y2- b.y1, a.x1 - b.x1, a.y1- b.y1); int d4 = mulplux(b.x2-b.x1, b.y2- b.y1, a.x2 - b.x1, a.y2- b.y1); //这个处理是为了防止d1*d2 或则d3*d4 溢出使得符号判断有误 d1 = dlcmp(d1); d2 = dlcmp(d2); d3 = dlcmp(d3); d4 = dlcmp(d4); if((d1*d2 > 0 || d3*d4 > 0)) return 0; //没有交点 if(d1 * d2 <0 && d3 * d4 < 0) return 3; //交与一点 ,情况4 //如果两条线段平行 if(d1 == d2 || d3 == d4) { if(online(a.x1,a.y1, a.x2, a.y2, b.x1, b.y1) || online(a.x1, a.y1, a.x2, a.y2, b.x2, b.y2)) return 1; //两条线段有无数个交点,情况2 else return 2; //两条线段只是在端点处相交,一个交点。情况3 //应该还有一种情况,就是没有交点,但是在前面没有交点的情况已经包括了 } //如果两条线段不平行,有一个线段的一个点在另一个线段上 if(d1 == 0 && d2 != 0 && online(a.x1,a.y1, a.x2, a.y2, b.x1, b.y1)) return 2; if(d1 != 0 && d2 == 0 && online(a.x1,a.y1, a.x2, a.y2, b.x2, b.y2)) return 2; if(d3 == 0 && d4 != 0 && online(b.x1, b.y1, b.x2, b.y2, a.x1, a.y1)) return 2; if(d4 == 0 && d3 != 0 && online(b.x1, b.y1, b.x2, b.y2, a.x2, a.y2)) return 2; return 0; } int main() { int t, i, j, k; cin >> t; while(t--) { cin >> N; for(i = 0; i< N; i++) cin >> Seg[i].x1 >> Seg[i].y1 >> Seg[i].x2 >> Seg[i].y2; for(i = 0; i< 4; i++) result[i] = 0; for(i = 0; i< N-1; i++) { for(j = i+1; j < N; j++) { result[panduan(Seg[i], Seg[j])]++; } } for(i = 0; i< 4; i++) { cout << result[i] << endl; } cout << endl; } return 0; }  

你可能感兴趣的:(BUPT final C题: 线段相交 -计算几何)