题目大意:给出线段起点,终点,之后给出矩形对角线的起点与终点,千万别天真按照样例就理解为是左上和右下点,不一定!
解题策略:今天下午开始看计算几何,初看题目第一反应是解析几何,但是误差太大,向量法完美解决本体,wa了好久,终于圆满解决,具体详见注释。
从这题开始AC所有计算几何吧!
/*
UVA 191 Intersection
AC by J_Dark
Time 0.016s
ON 2013/5/1 23:28
*/
#include
#include
#include
#include
#include
#include
#include
using namespace std;
struct point{
int x, y;
point(int a, int b){
x = a;
y = b;
}
};
vector line, rec; //定义线段, 矩形容器
bool ff; //记录线段与矩形相交标识
//////////////////////////////////
void Input(){
line.clear();
rec.clear();
int cLine_x, cLine_y, dLine_x, dLine_y, aRec_x, aRec_y;
int bRec_x, bRec_y, r1_x, r1_y, r2_x, r2_y;
cin >> cLine_x >> cLine_y >> dLine_x >> dLine_y >> r1_x >> r1_y >> r2_x >> r2_y;
//这里是wa点,输入矩形对角线的两个点不一定是按照左上,右下输入
//构造矩形对角线左上点与右下点
aRec_x = min(r1_x, r2_x);
aRec_y = max(r1_y, r2_y);
bRec_x = max(r1_x, r2_x);
bRec_y = min(r1_y, r2_y);
line.push_back(point(cLine_x, cLine_y));
line.push_back(point(dLine_x, dLine_y));
rec.push_back(point(aRec_x, aRec_y));
rec.push_back(point(aRec_x, bRec_y));
rec.push_back(point(bRec_x, aRec_y));
rec.push_back(point(bRec_x, bRec_y));
}
//计算 向量(pi-> pj)与(pj->pk)叉积,判断螺旋方向
int Direction(point Pi, point Pj, point Pk){
return (Pj.x-Pi.x)*(Pk.y-Pi.y)-(Pk.x-Pi.x)*(Pj.y-Pi.y);
}
//判断pk点是否在线段pi-pj上
bool OnSegment(point Pi, point Pj, point Pk){
if(min(Pi.x, Pj.x) <= Pk.x && max(Pi.x, Pj.x) >= Pk.x &&
min(Pi.y, Pj.y) <= Pk.y && max(Pi.y, Pj.y) >= Pk.y)
return true;
return false;
}
void Compute(){
//线段与矩形内部有相交 => 线段在矩形内
if((line[0].x >= rec[0].x) && (line[0].x <= rec[3].x) &&
(line[1].x >= rec[0].x) && (line[1].x <= rec[3].x) &&
(line[0].y <= rec[0].y) && (line[0].y >= rec[3].y) &&
(line[1].y <= rec[0].y) && (line[1].y >= rec[3].y))
ff = true;
//线段与矩形部分相交
else{
ff = false;
//枚举矩形四条边向量rec[0]->rec[1], rec[0]->[2], rec[3]->[1], rec[3]->[2]
//与线段向量line[0]->line[1]进行判断
for(int k=0; k<4; k+=3){
if(ff) break;
for(int i=1; i<=2; i++){
if(ff) break;
int d1, d2, d3, d4;
d1 = Direction(rec[k], rec[i], line[0]);
d2 = Direction(rec[k], rec[i], line[1]);
d3 = Direction(line[0], line[1], rec[k]);
d4 = Direction(line[0], line[1], rec[i]);
if(d1*d2<0 && d3*d4<0) { ff = true; break;} //规范相交
//非规范相交
else if(d1==0 && OnSegment(rec[k], rec[i], line[0])) {ff = true;}
else if(d2==0 && OnSegment(rec[k], rec[i], line[1])) {ff = true;}
else if(d3==0 && OnSegment(line[0], line[1], rec[k])) {ff = true;}
else if(d4==0 && OnSegment(line[0], line[1], rec[i])) {ff = true;}
else ff = false;
}
}
}
}
void Output(){
if(ff) cout << "T" << endl;
else cout << "F" << endl;
}
//////////////////////////////////
int main(){
int testCase;
while(cin >> testCase)
{
while(testCase--)
{
Input();
Compute();
Output();
}
}
return 0;
}