问题介绍:输入一堆以两点确认的线段,要求你通过判断那些线段是重叠的,然后给出一个最终实际多少条直线
问题剖析:这道题有两个需要解决的问题。1、怎样判断两条线是重合的,2、关于单精度浮点数与双精度浮点数的精确度问题
而第一个问题,我采用给每条线段计算其斜率、截距,以及其开始点与结束点的x值(需要考虑斜率不存在的情况,此时斜率保存为无限大,截距保存为x坐标,记录开始点与结束点的y值),然后通过每条线段的对比,首先是斜率、截距是否相同,再之其结束点是否在另一条直线的开始点之后。
而第二个问题,我用一个宏定义将EPS赋值1e-7,这代表了单精度浮点数的最大精确度,然后用自己的比较函数,判断两点差值是否小于这个值,来确保精确度的问题。
我在这道题使用了vector的数据结构,理由为vector提供的函数begin(),end(),这个两个都是返回random access iterator,才能满足stl里sort函数的使用,而list的begin(),end()返回的只是bidirection iterator,也试想过用set这个可以自动排序的容器,但是其加入项的方法比较麻烦。
下面是我的代码
#include<iostream>
#include<algorithm>
#include<vector>
using namespace std;
#define INF 1e+15
#define EPS 1e-7
int compare(double x1, double x2) { // float compare
if (x1 - x2 < -EPS)
return -1;
if (x1 - x2 > EPS)
return 1;
return 0;
}
class Line {
private:
double start;
double end;
double k;
double b;
public:
Line() {}
Line(double sx, double sy, double ex, double ey) {
if (compare(ex, sx) == 0) {
k = INF; // if k is not exist, put an infinite
b = sx;
start = sy; // store the number of y
end = ey;
} else {
k = (ey - sy) / (ex - sx);
b = sy - k * sx;
start = sx;
end = ex;
}
}
Line(const Line& l) {
k = l.k;
b = l.b;
start = l.start;
end = l.end;
}
float getStart() const {
return start;
}
float getEnd() const {
return end;
}
double getK() const {
return k;
}
double getB() const {
return b;
}
};
struct mycmp {
bool operator() (Line l1, Line l2) const {
if (compare(l1.getK(), l2.getK()) == 0) {
if (compare(l1.getB(), l2.getB()) == 0) {
return compare(l1.getStart(), l2.getStart()) < 0;
}
return compare(l1.getB(),l2.getB()) < 0;
}
return compare(l1.getK(), l2.getK()) < 0;
}
} cmp;
int main(void) {
int n;
cin >> n;
while (n != 0) {
vector<Line> lines;
int i, num;
double x1, y1, x2, y2;
double maxend;
for (i = 0; i < n; ++i) {
cin >> x1 >> y1 >> x2 >> y2;
if (compare(x1, x2) > 0) {
swap(x1, x2);
swap(y1, y2);
}
else if (compare(x1, x2) == 0){
if (compare(y1, y2) > 0)
swap(y1, y2);
}
lines.push_back(Line(x1, y1, x2, y2));
}
sort(lines.begin(), lines.end(), cmp);
num = lines.size();
maxend = lines.front().getEnd();
vector<Line>::iterator it1, it2;
for (it1 = lines.begin(), it2 = it1, ++it2; it2 != lines.end(); ++it2, ++it1) {
if (compare((*it1).getK(), (*it2).getK()) == 0 && compare((*it1).getB(), (*it2).getB()) == 0) {
if ((*it2).getStart() <= maxend)
--num;
if (maxend < (*it2).getEnd())
maxend = (*it2).getEnd();
}
else
maxend = (*it2).getEnd();
}
cout << num << endl;
cin >> n;
}
return 0;
}
参考资料
http://blog.csdn.net/xiehaoyun2012/article/details/8438257