題意:給了很多線段,點的座標都是整數,並且絕對值 <1000,如果某一條線段和其他任何一條線段都不想交,就是被隔離的,求出被隔離線段的個數
解題:每一條都去和剩下的線段判斷是否相交,只要相交就不是了,如果沒有和它相交的,被隔離的線段數就加一
WA:這是一個非常有意義的錯誤,而且不容易發現。題目給出的點的座標都是整數,而且都是小於1000,所以我放心的用INT,但是 向量的叉積就可能是1e6級別的,用INT會溢出,所以把求叉積的變量至少設爲double型纔可以。但是爲了完成判相等的操作,最好用long long int,浮點數判相等要用到abs(double) < eps。以後的編程過程中,不能簡單看輸入數據的類型和範圍,要考慮到每一個函數的結果可能的最大範圍。
代碼:
//uva11343 Isolated Segments
//AC By Warteac
//Runtime:0.019s
//2013-5-8
#include<iostream>
#include<cstdio>
#include<vector>
#include<cstring>
using namespace std;
struct point{
int x,y;
point(int x1 = 0, int y1 = 0){x = x1; y = y1;}
void print(){cout << "x= " << x << " y= " << y << endl;}
};//定義點結構體
//求向量的叉積,p1*p2 > 0 => p1 在 p2的順時針方向,< 0 逆時針
long long 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 &&
pk.x <= max(pi.x,pj.x) &&
min(pi.y,pj.y) <= pk.y &&
pk.y <= max(pi.y,pj.y) ){
return true;
}else{
return false;
}
}
//線段(p1,p2)和線段(p3,p4)是否相交
bool segmentsIntersect(point p1,point p2,point p3, point p4){
long long d1,d2,d3,d4; // int WA many times,double is not the best,long long is recommended
d1 = direction(p3,p4,p1);
d2 = direction(p3,p4,p2);
d3 = direction(p1,p2,p3);
d4 = direction(p1,p2,p4);
//cout << d1 << " " << d2 <<" " << d3 << " " << d4 << endl;
if((d1*d2 < 0) && (d3*d4 < 0))
return true;
else if((d1 == 0)&&(onSegment(p3,p4,p1)))
return true;
else if((d2 == 0)&&(onSegment(p3,p4,p2)))
return true;
else if((d3 == 0)&&(onSegment(p1,p2,p3)))
return true;
else if((d4 == 0)&&(onSegment(p1,p2,p4)))
return true;
else return false;
}
int computing(vector <point> v ,int n){
int r = 0,i,j;
bool flag;
for(i = 0; i < n; i++){
//cout << "i = " << i << endl;
flag = false;
for(j = 0; j < n; j++){
//cout << "j = " << j << endl;
if(j == i) continue;
if(segmentsIntersect(v[2*i],v[2*i+1],v[2*j],v[2*j+1])){
flag = true;
break;
}
}
if(!flag)
r++;
}
return r;
}
//////////////////////////////////////////////////
int main(){
int caseNum,x;
cin >> caseNum;
vector <point> vPoint;
for(x = 0; x < caseNum; x++){
int num;//num of segments
cin >> num;
int Xpi,Ypi,Xei,Yei;
vPoint.clear();
for(int i = 0; i < num; i++){
cin >> Xpi >> Ypi >> Xei >> Yei;
point p(Xpi,Ypi);
vPoint.push_back(p);
point q(Xei,Yei);
vPoint.push_back(q);
}
//cout <<"num = " << num << endl;
cout << computing(vPoint,num) << endl ;
}
return 0;
}