題目大意:給出一組線段,若每組線段有相交,則線段有交點處斷開,生成新的線段,求出最後所有線段數目
解題策略:經過驗證,該題相交情況爲“規範相交”,難度大大降低。
我的核心算法是:對一個線段來說,記錄它與其他所有線段規範相交點的數目,斷開生成新線段數目 = 相交點數目+1。
/*
UVA 866 Intersecting Line Segments
AC by J_Dark
ON 2013/5/3
Time 0.009s
*/
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <climits>
#include <vector>
#include <algorithm>
using namespace std;
struct point{
double x, y;
point(double p=0, double q=0){
x = p;
y = q;
}
};
struct line{
point a, b;
line(point x, point y){
a = x;
b = y;
nn = 0;
}
int nn;
};
int segNum;
vector <line> Seg;
///////////////////////////////////////////
void Input(){
Seg.clear();
double ax, ay, bx, by;
cin >> segNum;
for(int i=0; i<segNum; i++){
cin >> ax >> ay >> bx >> by;
point start(ax, ay), end(bx, by);
Seg.push_back(line(start, end));
}
}
double Direction(point Pi, point Pj, point Pk){
return (Pj.x-Pi.x)*(Pk.y-Pi.y)-(Pk.x-Pi.x)*(Pj.y-Pi.y);
}
bool isIntersect(line p, line q){
double d1, d2, d3, d4;
d1 = Direction(p.a, p.b, q.a);
d2 = Direction(p.a, p.b, q.b);
d3 = Direction(q.a, q.b, p.a);
d4 = Direction(q.a, q.b, p.b);
if(d1*d2<0 && d3*d4<0) { return true;} //規範相交
//非規範相交
else return false;
}
void Compute(){
int newSegNum = 0;
for(int i=0; i<segNum; i++){
for(int k=0; k<segNum; k++){
if(i != k){
if(isIntersect(Seg[i], Seg[k]))
Seg[i].nn++;
}
}
newSegNum += (Seg[i].nn + 1);
}
/*for(int i=0; i<segNum; i++){
cout << Seg[i].nn << endl;}*/
cout << newSegNum << endl;
}
///////////////////////////////////////////////////////
int main(){
int testCase;
while(cin >> testCase)
{
getchar();
getchar();
for(int i=0; i<testCase; i++){
if(i>0) cout << endl;
Input();
Compute();
}
}
return 0;
}