题目链接在此
参考的是这位大神的解题方法
这题要考虑的情况有很多。
另外两个double类型数据不能简单地以==来判断相等!
以下是源代码:
#include<iostream>
#include<cmath>
#include<algorithm>
using namespace std;
#define INFINITE 10000.00
bool equal(double a, double b) { //两个double类型数据不能简单地以==来判断相等
return fabs(a - b) < 1e-6;
}
struct line {
double k, b;
double x1, y1, x2, y2;
line() {}
line(double xx1, double yy1, double xx2, double yy2, double kk, double bb)
: x1(xx1), y1(yy1), x2(xx2), y2(yy2), k(kk), b(bb) {}
// 对线段(x1,y1)-(x2,y2)转化成 y=kx+b 形式,进行排序,按照 k 升序排序,如果 k 值相等,则按 b 值升序排序,
// 如果 k,b都相等,则按 x1 升序排序,若 x1 还相等的话,则按 x2 升序排序。
// 要对 平行于 y轴,即斜率不存在的线段 加以判断,
// 先按照 b 值(b==x1)升序排序,再按 y1 升序排序,最后按 y2 升序排序
bool operator<(const line& other) const{ // 自定义比较函数
if (equal(k, other.k)){
if (equal(k, INFINITE)) {
if (equal(b, other.b)) {
if (equal(y1, other.y1))
return y2 < other.y2;
else
return y1 < other.y1;
}
else
return b < other.b;
}
else if (equal(b, other.b)) {
if (x1 == other.x1)
return x2 < other.x2;
else
return x1 < other.x1;
}
else
return b < other.b;
}
else
return k<other.k;
}
} s[10000];
int main() {
int lineNum;
double x1, y1, x2, y2;
while (cin >> lineNum && lineNum != 0) {
for (int i = 0; i < lineNum; i++) {
cin >> x1 >> y1 >> x2 >> y2;
if (x1 > x2 || (equal(x1, x2) && y1 > y2)) { //保证x1<x2或斜率不存在时有y1<y2
swap(x1, x2);
swap(y1, y2);
}
if (equal(x1, x2))
s[i] = line(x1, y1, x2, y2,INFINITE,x1);
else {
s[i] = line(x1, y1, x2, y2, (y2 - y1) / (x2 - x1), 0);
s[i].b = y1 - s[i].k * x1;
}
}
sort(s, s + lineNum);
int counter = 1;
double farX = s[0].x2, farY = s[0].y2; //(farX,farY)记录当前线段的终点
for (int i = 1; i < lineNum; i++) {
//如果k 或者b 不相等,则肯定不在同一直线上
if (!equal(s[i].k, s[i - 1].k) || !equal(s[i].b, s[i - 1].b)) {
farX = s[i].x2;
farY = s[i].y2;
counter++;
}
//在同一直线上但没有公共部分
else if ((s[i].k != INFINITE && s[i].x1 > farX) || (s[i].k == INFINITE && s[i].y1 > farY)) {
farX = s[i].x2;
farY = s[i].y2;
counter++;
}
//在同一直线上而且有公共部分,如果当前线段的终点更远,那也要更新(x,y)
else if ((s[i].k != INFINITE && farX < s[i].x2) || (s[i].k == INFINITE && farY < s[i].y2)) {
farX = s[i].x2;
farY = s[i].y2;
}
}
cout << counter << endl;
}
return 0;
}