题目不难,但是对精度要求很高,所以 double 类型不能直接比较大小,需要借助一个趋于零的正数(如 1e-8)比较。
#include <iostream>
#include <algorithm>
#include <cmath>
using namespace std;
const int MAXN = 10005;
struct segment //线段
{
double x1, y1; //点1
double x2, y2; //点2
double k, b; //斜率,y轴截距(y=kx+b)
bool flag; //斜率是否存在(x1和x2是否不相等)
}seg[MAXN];
//浮点数a和b是否相等
int isSame(double a, double b)
{
if (fabs(a - b) > 1e-8)
return 0;
else
return 1;
}
//浮点数a是否不大于b
int isSmaller(double a, double b)
{
if (a - b > 1e-8)
return 0;
else
return 1;
}
//排序标准
bool cmp(segment a, segment b)
{
if (a.flag != b.flag) //斜率不存在的在前
return a.flag < b.flag;
else
{
if (a.flag != 0) //斜率都存在
{
if (!isSame(a.k, b.k))
return isSmaller(a.k, b.k);
else
{
if (!isSame(a.b, b.b))
return isSmaller(a.b, b.b);
else
{
if (!isSame(a.x1, b.x1))
return isSmaller(a.x1, b.x1);
else
return isSmaller(a.x2, b.x2);
}
}
}
else //斜率都不存在
{
if (!isSame(a.x1, b.x1))
return isSmaller(a.x1, b.x1);
else
return isSmaller(a.y1, b.y1);
}
}
}
//选择浮点数a和b中的较大值
double MAX(double a, double b)
{
if (a - b > 1e-10)
return a;
else
return b;
}
//线段a和线段b是否连接(斜率相同,有交点)
int isDoublication(segment& a, segment& b)
{
if (a.flag != b.flag)
return 0;
if (a.flag != 0) //斜率都存在
{
if (!isSame(a.k, b.k))
return 0;
else if (!isSame(a.b, b.b))
return 0;
else if (b.x1 - a.x2 > 1e-8)
return 0;
else
{
b.x2 = MAX(a.x2, b.x2);
return 1;
}
}
else
{
if (isSame(a.x1, b.x1) && b.y1 - a.y2 < 1e-8)
{
b.y2 = MAX(b.y2, a.y2);
return 1;
}
else
return 0;
}
}
int main()
{
int n;
while (cin >> n)
{
if (n == 0)
break;
for (int i = 0; i < n; i++)
{
cin >> seg[i].x1 >> seg[i].y1 >> seg[i].x2 >> seg[i].y2;
if (seg[i].x1 == seg[i].x2) //直线斜率不存在
{
seg[i].flag = 0;
if (seg[i].y1 > seg[i].y2)
swap(seg[i].y1, seg[i].y2);
}
else
{
seg[i].flag = 1;
if (seg[i].x1 > seg[i].x2)
{
swap(seg[i].x1, seg[i].x2);
swap(seg[i].y1, seg[i].y2);
}
seg[i].k = (seg[i].y2 - seg[i].y1) / (seg[i].x2 - seg[i].x1);
seg[i].b = seg[i].y1 - seg[i].k * seg[i].x1;
}
}
sort(seg, seg + n, cmp);
int total = 1; //总线段数
for (int i = 1; i < n; i++)
{
if (!isDoublication(seg[i - 1], seg[i]))
++total;
}
cout << total << endl;
}
return 0;
}
继续加油。