/*1004. I Conduit!
题目大意:给出一堆线段,求出需要画出最少的直线就可覆盖全部线段
即有一部分重叠的线段用一条直线代表即可。
思路:先对每条线段求出其斜率k和截距b(如果没有截距,则用无限大代表)
然后记录每条线段的起始位置(如果无斜率则为y坐标的较小的那个,如果
有斜率,则为x坐标较小的那个),结束位置则取较大的那个。
然后把线段数组先按k,后按b,最后按起始位置start从小到大排序
排好序后,保证了同一直线上的线段在同一个区域内。
然后先取出第一条线段的结束位置maxEnd,然后依次往后遍历,发现k和b相等的,
即说明是同一条直线,就比较该线段的其实位置start与maxEnd的大小,如果是
start在maxEnd前面,说明重叠,需要画的线段数num--,然后更新maxEnd。
如果发现不重叠,就更新maxEnd
*/
#include<iostream>
#include<stdlib.h>
#include<algorithm>
using namespace std;
#define INF 1e+15
#define EPS 1e-7
int cmp(double x1, double x2){
if(x1 - x2 < -EPS)
return -1;
if(x1 - x2 > EPS)
return 1;
return 0;
}
struct Line{
double k;
double b;
double start, end;
Line(){
}
Line(double x1, double y1, double x2, double y2 ){
if(cmp(x1, x2) == 0){
k = INF;
b = x1;
start = min(y1, y2);
end = max(y1, y2);
}
else{
k = (y1 - y2)/(x1 - x2);
b = y1 - k * x1;
start = min(x1, x2);
end = max(x1, x2);
}
}
};
bool cmpLine(Line a, Line b){
if(cmp(a.k, b.k) != 0)
return cmp(a.k,b.k ) < 0;
if(cmp(a.b, b.b) != 0)
return cmp(a.b,b.b ) < 0;
return cmp(a.start, b.start) < 0;
}
int n;
Line line[10000];
int main()
{
while(cin >> n && n!=0){
for(int i=0; i<n; i++) {
double startX , startY, endX, endY;
cin >> startX >> startY >> endX >> endY;
line[i] = Line(startX, startY, endX, endY);
}
sort(line, line+n, cmpLine);
int num = n;
double maxEnd = line[0].end;
for(int i=1; i<n; i++){
if(cmp(line[i].k, line[i-1].k) == 0 && cmp(line[i].b, line[i-1].b) == 0)
{
if(cmp(line[i].start, maxEnd)<= 0 )
num--;
maxEnd = max(maxEnd, line[i].end);
}
else
maxEnd = line[i].end;
}
cout << num << endl;
}
system("pause");
return 0;
}
Sicily.1004. I Conduit!
最新推荐文章于 2020-03-22 21:00:39 发布