POJ 2036 I Conduit!

 

I Conduit!
Time Limit: 2000MS   Memory Limit: 30000K
Total Submissions: 1313   Accepted: 245

Description

Irv Kenneth Diggit works for a company that excavates trenches, digs holes and generally tears up people's yards. Irv's job is to make sure that no underground pipe or cable is underneath where excavation is planned. He has several different maps, one for each utility company, showing where their conduits lie, and he needs to draw one large, consolidated map combining them all. One approach would be to simply draw each of the smaller maps one at a time onto the large map. However, this often wastes time, not to mention ink for the pen-plotter in the office, since in many cases portions of the conduits overlap with each other (albeit at different depths underground). What Irv wants is a way to determine the minimum number of line segments to draw given all the line segments from the separate maps.

Input

Input will consist of multiple input sets. Each set will start with a single line containing a positive integer n indicating the total number of line segments from all the smaller maps. Each of the next n lines will contain a description of one segment in the format

x1 y1 x2 y2

where (x1,y1) are the coordinates of one endpoint and (x2,y2) are the coordinates of the other. Coordinate values are floating point values in the range 0...1000 speci.ed to at most two decimal places. The maximum number of line segments will be 10000 and all segments will have non-zero length. Following the last input set there will be a line containing a 0 indicating end of input; it should not be processed.

Output

For each input set, output on a single line the minimum number of line segments that need to be drawn on the larger, consolidated map.

Sample Input

3
1.0 10.0 3.0 14.0
0.0 0.0 20.0 20.0
10.0 28.0 2.0 12.0
2
0.0 0.0 1.0 1.0
1.0 1.0 2.15 2.15
2
0.0 0.0 1.0 1.0
1.0 1.0 2.15 2.16
0

Sample Output

2
1
2

Source

East Central North America 2004

 

 

/* 呵呵,这题进前20了 13 6262545 bobten2008 732K 141MS C++ 2246B 2009-12-20 14:52:15 很恶心的计算几何问题,核心思想是利用排序将seg按照斜率进行排序,容易错误的地方有四点 1)精度问题,需要加eps修正. 2)输入数据中的每个seg的两个点的顺序不是按照从左到右或者从下到上,因此需要调整seg的 两个端点比如对于线短1 2 3 2,也有可能以3 2 1 2的形式出现,我在这里统一调成从下到上, 从左到右的顺序,这里如果不调整可能会影响后续的工作. 3)排序算法的比较函数,比较复杂,需要考虑竖线(即没有斜率的情况),详见正文里的注释 4)最后顺序扫描排序后的seg时,需要调整当前seg的x2或者y2值,比如对于 [1 2 10 2], [2 2 5 2] [6 2 12 2]这组数据,排序完也是这个顺序,那么第二个seg被包含在第一个 seg里,如果不修正第二个seg的y2坐标,那么在处理第三个seg时,第三个seg肯定不被包含进来,那么 最后答案是2,其实这组数据的答案应该是1.所以在处理完第二个seg后需要将其y2修正为10. 具体怎么修正呢,很简单,只要取y2为当前seg的y2和上一个seg的y2的最大值即可 算法的时间复杂度是O(nlgn) */ #include <iostream> #include <algorithm> #include <cmath> #define EPS 1e-8 #define MAX_N 10005 using namespace std; struct seg { double x1, y1, x2, y2; bool spe; //spe = true表示当前seg与y轴平行,否则不平行,与y轴平行时是没有斜率的 double a, b; }segs[MAX_N]; int n; //比较函数,核心思想是把没有斜率(与y轴平行)的放在有斜率的后面,把斜率小的放在斜率大的前面 //对于具有相同斜率的seg,把与y轴交点低的放在前面 //对于在一条线上的seg,把x坐标(当与y轴平行时比较y坐标)小的放在前面 bool compare(const seg &seg1, const seg &seg2) { //两个seg都没有斜率 if(seg1.spe && seg2.spe) return fabs(seg1.x1 - seg2.x1) < EPS ? seg1.y1 < seg2.y1 + EPS : seg1.x1 < seg2.x2 + EPS; else if(seg1.spe && !seg2.spe) return false; //一个有斜率一个没有斜率,把有斜率的放在前面 else if(!seg1.spe && seg2.spe) return true; else //两个seg都有斜率 { //斜率相等时需要比较与y轴的交点,当焦点也相等时需要比较左端点x值的大小 if(fabs(seg1.a - seg2.a) < EPS) return fabs(seg1.b - seg2.b) < EPS ? seg1.x1 < seg2.x1 + EPS : seg1.b < seg2.b + EPS; else return seg1.a < seg2.a + EPS; } } void swap(double &d1, double &d2) { double temp = d1; d1 = d2; d2 = temp; } //判断两个seg是否相交, type用来区分这个两个seg与y轴的平行情况,type = 0时表示与y轴平行 bool cross(const seg& seg1, const seg &seg2, bool type) { if(!type) return seg2.y1 <= seg1.y2; else return seg2.x1 <= seg1.x2; } int main() { int i; while(scanf("%d", &n) && n != 0) { for(i = 0; i < n; i++) { scanf("%lf%lf%lf%lf", &segs[i].x1, &segs[i].y1, &segs[i].x2, &segs[i].y2); if(segs[i].x1 > segs[i].x2 + EPS) { swap(segs[i].x1, segs[i].x2); swap(segs[i].y1, segs[i].y2);} else if(fabs(segs[i].x1 - segs[i].x2) < EPS && segs[i].y1 > segs[i].y2 + EPS) { swap(segs[i].x1, segs[i].x2); swap(segs[i].y1, segs[i].y2); } segs[i].spe = false; if(fabs(segs[i].x1 - segs[i].x2) < EPS) segs[i].spe = true; else { segs[i].a = (segs[i].y2 - segs[i].y1) / (segs[i].x2 - segs[i].x1); segs[i].b = segs[i].y1 - segs[i].x1 * segs[i].a; } } sort(segs, segs + n, compare); int countv = 1; for(i = 1; i < n; i++) { //当前seg与y轴平行其与上一个seg相交 if(segs[i].spe && segs[i - 1].spe && fabs(segs[i].x1 - segs[i - 1].x1) < EPS && cross(segs[i - 1], segs[i], false)) { //调整当前seg的y2 if(segs[i].y2 < segs[i - 1].y2 + EPS) segs[i].y2 = segs[i - 1].y2; continue; } //当前seg不与y轴平行且与上一个seg相交 if(!segs[i].spe && !segs[i - 1].spe && fabs(segs[i].a - segs[i - 1].a) < EPS && fabs(segs[i].b - segs[i - 1].b) < EPS && cross(segs[i - 1], segs[i], true)) { //调整当前seg的x2 if(segs[i].x2 < segs[i - 1].x2 + EPS) segs[i].x2 = segs[i - 1].x2; continue; } //找到一个新的不可与上一个seg合并的seg则需要为countv的值增加1 countv++; } printf("%d/n", countv); } return 0; } 

你可能感兴趣的:(算法,Integer,Office,input,each,output)