題目大意:給出線段起點,終點,之後給出矩形對角線的起點與終點,千萬別天真按照樣例就理解爲是左上和右下點,不一定!
解題策略:今天下午開始看計算幾何,初看題目第一反應是解析幾何,但是誤差太大,向量法完美解決本體,wa了好久,終於圓滿解決,具體詳見註釋。
從這題開始AC所有計算幾何吧!
/*
UVA 191 Intersection
AC by J_Dark
Time 0.016s
ON 2013/5/1 23:28
*/
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <climits>
#include <vector>
#include <algorithm>
using namespace std;
struct point{
int x, y;
point(int a, int b){
x = a;
y = b;
}
};
vector<point> 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;
}