这是一道比较简单的判断线是否相交的题。
题意是:
每个case给出ABC三条线:
Line A 的起始点 (x1, y1) & 终点 (x2, y2)
Line B 的起始点 (x1, y1) & 终点 (x2, y2)
Line C 的起始点 (x1, y1) & 终点 (x2, y2)
有五种可能的关系:
1. 三条线都不想交
2.AB相交,C与它们分离
3.BC相交,A与它们分离
4.AC相交,B与它们分离
5.ABC都相交
在下手写之前,先理解一下可以用的方法
请参考下面的文档,我觉得写得特别的好:
http://hsfzxjy.github.io/the-simplest-way-to-find-out-if-two-segments-are-intersected/
基本思路是
bool checkCross(line1,line2) {
if(两条线平行且重叠) {
return true;
}
if(两线相交) { // direct(AC, AD) != direct(BC, BD)
且 direct(CA, CB) != direct(DA, DB)
return true;
}
return false;
}
具体的判断是判断方向,判断方向是点和线
当向量叉积为0是判断是否重叠
// if direct(a,b) is clockwise, 180<=<a,b><=360, sin<a,b> <= 0
// while anticlockwise 0<=<a,b><=180, sin<a,b> >=0
int checkDirect(Line l, Point p) {
Vect v1 = makeVect(p,l.start);
Vect v2 = makeVect(p,l.end);
int direct = v1.x*v2.y - v2.x*v1.y; // cout the direct of v1 and v2 vector
if(direct == 0) {
if(checkInside(l,p)) {
return 2;
} else {
return 0;
}
} else {
return direct>0?1:-1;
}
}
重叠的判断方法:
bool checkInside(Line l, Point p) { // check whether point inside the line
int lX = getMin(l.start.x, l.end.x);
int rX = getMax(l.start.x, l.end.x);
int lY = getMin(l.start.y, l.end.y);
int rY = getMax(l.start.y, l.end.y);
if(lX<=p.x && p.x<=rX && lY<=p.y && p.y<=rY) {
return true;
} else {
return false;
}
}
全套的代码:
#include <cstdio>
#include <iostream>
using namespace std;
#define TEST
#define NUM 3
#define getMin(a,b) a<b?a:b
#define getMax(a,b) a>b?a:b;
int result[3][3];
int ans[3];
typedef struct {
int x;
int y;
}Point;
typedef struct {
int x;
int y;
}Vect;
typedef struct {
Point start;
Point end;
Vect v;
}Line;
Line line[3];
Vect makeVect(Point p1, Point p2) {
Vect tmp;
tmp.x = p2.x-p1.x;
tmp.y = p2.y-p1.y;
return tmp;
}
bool checkInside(Line l, Point p) { // check whether point inside the line
int lX = getMin(l.start.x, l.end.x);
int rX = getMax(l.start.x, l.end.x);
int lY = getMin(l.start.y, l.end.y);
int rY = getMax(l.start.y, l.end.y);
if(lX<=p.x && p.x<=rX && lY<=p.y && p.y<=rY) {
return true;
} else {
return false;
}
}
// if direct(a,b) is clockwise, 180<=<a,b><=360, sin<a,b> <= 0
// while anticlockwise 0<=<a,b><=180, sin<a,b> >=0
int checkDirect(Line l, Point p) {
Vect v1 = makeVect(p,l.start);
Vect v2 = makeVect(p,l.end);
int direct = v1.x*v2.y - v2.x*v1.y; // cout the direct of v1 and v2 vector
if(direct == 0) {
if(checkInside(l,p)) {
return 2;
} else {
return 0;
}
} else {
return direct>0?1:-1;
}
}
bool checkCross(Line l1, Line l2) {
#ifdef TEST
cout<<"checkDirect(l2, l1.start) = "<<checkDirect(l2, l1.start)<<" compare checkDirect(l2, l1.end) = "<< checkDirect(l2, l1.end)<<endl;
cout<<"checkDirect(l1, l2.start) = "<<checkDirect(l1, l2.start)<<" compare checkDirect(l1, l2.end) = "<< checkDirect(l1, l2.end)<<endl;
#endif
if(checkDirect(l2, l1.start) == 2 || checkDirect(l2, l1.end)==2 || checkDirect(l1, l2.start) == 2 || checkDirect(l1, l2.end) == 2) {
return true;
}
// The necessary and sufficient condition is direct(AC,AD)!=direct(BC,BD) && direct(CA,CB)!=direct(DA,DB)
if(checkDirect(l2, l1.start) != checkDirect(l2, l1.end)) {
if(checkDirect(l1, l2.start)!= checkDirect(l1, l2.end)) {
return true;
}
}
return false;
}
void printResult() {
cout<<"result:"<<endl;
int i,j;
for(i=0;i<NUM;i++) {
for(j=0;j<NUM;j++) {
cout<<result[i][j]<<" ";
}
cout<<endl;
}
}
void printAnswer() {
int i,j;
char def = 'A';
bool mark=false;
for(i=0;i<NUM;i++) {
for(j=i+1;j<NUM;j++) {
if(result[i][j]==1)
{
ans[i]=1;
ans[j]=1;
mark = true;
}
}
}
if(mark == false) {
cout<<"X";
} else {
for(i=0;i<NUM;i++) {
if(ans[i]==1){
cout<<(char)(def+i);
}
}
}
cout<<endl;
#ifdef TEST
cout<<"ans:"<<endl;
for(i=0;i<NUM;i++) {
cout<<ans[i]<<" ";
}
cout<<endl;
#endif
}
void init() {
int i,j;
for(i=0;i<NUM;i++) {
for(j=0;j<NUM;j++) {
if(i==j) {
result[i][j] = -1;
} else {
result[i][j] = 0;
}
}
ans[i] = 0;
}
}
int main(int argc, char** argv)
{
int tc, T;
int i,j;
freopen("input.txt", "r", stdin);
cin >> T;
for(tc = 0; tc < T; tc++)
{
init();
for(i=0; i<NUM; i++) {
cin>>line[i].start.x;
cin>>line[i].start.y;
cin>>line[i].end.x;
cin>>line[i].end.y;
line[i].v.x = line[i].end.x - line[i].start.x;
line[i].v.y = line[i].end.y - line[i].start.y;
}
for(i=0;i<NUM;i++) {
for(j=i+1;j<NUM;j++) {
if(i!=j) {
bool r = checkCross(line[i],line[j]);
if(r == true) {
result[i][j] = 1;
result[j][i] = 1;
}else {
result[i][j] = 0;
result[j][i] = 0;
}
}
}
}
#ifdef TEST
printResult();
#endif
printAnswer();
}
return 0;//Your program should return 0 on normal termination.
}