sicily 1004. I Conduit!

//给出各线段的起点和终点,如果两条线段在同一直线上且有重合部分(包括一个点)则可以合并成一条线段,
//问最后剩多少条线段
//对线段(x1,y1)-(x2,y2)转化成 y=kx+b 形式,进行排序,按照 k 升序排序,如果 k 值相等,则按 b 值升序排序,
//如果 k,b都相等,则按 x1 升序排序,若 x1 还相等的话,则按 y1 升序排序。
//要对 平行于 y轴,即斜率不存在的线段 加以判断,
//先按照 b 值(b=x1)升序排序,再按 y1 升序排序,最后按 y2 升序排序

#include
<iostream>
#include
<algorithm>
#include
<cmath>
using namespace std;
#define vert 99999 //表示斜率不存在
bool equal(double a,double b) //两个double类型数据不能简单地以==来判断相等
{
return fabs(a-b)<1e-6;
}
struct Node
{
double x1,x2,y1,y2;
double k,b; //k是斜率,b是截距
bool operator<(const Node& other)const //自定义比较函数
{
if(equal(k,other.k))
{
if(k==vert)
{
if(equal(b,other.b))
{
if(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;
}
}line[
10000];
int main()
{
int n;
double x1,x2,y1,y2;
while(cin>>n&&n)
{
for(int i=0;i<n;++i)
{
cin
>>x1>>y1>>x2>>y2;
if(x1>x2||(x1==x2&&y1>y2))
{
swap(x1,x2);swap(y1,y2);
//保证 x1<x2 或者 y1<y2(斜率不存在时)
}
line[i].x1
=x1;line[i].y1=y1;line[i].x2=x2;line[i].y2=y2;
if(x1!=x2)
{
line[i].k
=(y2-y1)/(x2-x1);
line[i].b
=y1-line[i].k*x1; //y=kx+b
}
else
{
line[i].k
=vert;
line[i].b
=x1;
}
}
sort(line,line
+n);
int s=1;
double x=line[0].x2,y=line[0].y2; //(x,y)记录当前线段的终点
for(int i=1;i<n;++i)
{
if( !equal(line[i].k,line[i-1].k) || !equal(line[i].b,line[i-1].b) ) //如果k 或者b 不相等,则自然不在同一直线上
{
s
++;
x
=line[i].x2;y=line[i].y2;
}
else if( (line[i].k!=vert&&line[i].x1>x) || (line[i].k==vert&&line[i].y1>y) ) //在同一直线上但没有公共部分
{
s
++;
x
=line[i].x2;y=line[i].y2;
}
else if( (line[i].k!=vert&&x<line[i].x2) || (line[i].k==vert&&y<line[i].y2) ) //在同一直线上而且有公共部分,如果当前线段的终点更远,那也要更新(x,y)
{
x
=line[i].x2;y=line[i].y2;
}
}
cout
<<s<<endl;
}
return 0;
}

posted on 2011-07-04 11:05  sysu_mjc  阅读(510)  评论(0编辑  收藏  举报

导航