计算几何入门题之点,线,面,形基本关系以及点积叉积的理解
2012-08-26 14:57
507 查看
本人菜鸟一只,暑期做了一点计算几何的题目,现先将我之前转载的《计算几何题目推荐》的入门题的第一部分的解答与大家分享。
本篇所涉的题主要是与点,线,面,形基本关系以及点积叉积的理解相关的15道题,相对还是很基础的。但我这弱菜做的不太轻松。
POJ 2318 TOYS
题意:判断箱子每个块内有多少个玩具
分析:对于每个玩具的坐标,采用二分查找以确定玩具所在的块,其中玩具与分界(线段)的位置关系的判断可通过叉积来实现。
代码:
POJ 2398 Toy Storage
题意:与上一题一样,只是输出不同
代码:
POJ 3304 Segment
题意:判断是否存在一条直线,使得n条线段在该直线上的投影存在公共部分。
分析:若存在这样一条直线,过投影相交区域作直线的垂线,该垂线必定与每条线段相交,问题转化为问是否存在一条线和所有线段相交;
若存在一条直线与所有线段相机相交,将该线旋转,平移,直到不能再动为止,此时该直线必定经过这些线段的某两个端点;
所以枚举任意两个端点即可,注意还要判重。(此思路是借鉴的别人的)
代码:
POJ 1269 Intersecting Lines
题意:直线相交判断(不相交、共线、相交),相交求交点
分析:没啥好分析的,略啦
代码:
POJ 1556 The Doors
题意:求从(0,5)到(10,5)的最短距离,之间有墙和门。
分析:黑书上的一道习题,个人觉得此题主要是Dijkstra算法的应用,其次是线段相交的判断。
代码:
POJ 2653 Pick-up sticks
题意:按顺序放置一定数量的枝条(线段),找到所有的不被压的枝条。
分析:针对每一个枝条,遍历在其后放的枝条,判断是否相交,若都不相交,则是符合条件的。
代码:
POJ 1066 Treasure Hunt
题意:在一个矩形区域内,有n条线段,线段的端点是在矩形边上的有一个特殊点end,问从这个点到矩形边的最少经过的线段(实际穿过线段时只能穿过中点)
分析:首先要要理解穿过最少门的意思,其实只要枚举end与矩形边上每小段的中点mid连线与几条线段相交就OK了。
代码:
POJ 1410 Intersection
题意:判断给定线段是否与矩形相交
分析:很简单的题,将线段与矩形的四条边一次比较即可。此题还需注意的有:(1)线段在矩形内也算相交,不然过不了;(2)给出的左上顶点和右下顶点不保证x1<x2,y1>y2;即需要自己判断
代码:
POJ 1696 Space Ant
题意:一只蚂蚁,只会向左转,现在给出平面上很多个点,求解一种走法,能使得蚂蚁能经过的点最多,每个顶点该蚂蚁只能经过一次,且所行走的路线不能发生交叉。
分析:这题考查了凸包的性质,是Graham算法的应用。先选取最左下方的(下的优先级比左高)点,然后对剩下的点进行极角排序,选取最小的;重复操作,直至所有的点都被选中输出。其实无论输入什么样的点集,一定可以走完全部n个点的,这是凸包的性质决定。
代码:
POJ 3347 Kadj Squares
题意:给n个正方形,要求45°角放置,最左边的正方形紧贴Y轴,所有的正方形的下面的端点都在X轴上。然后按照正方形不能交错但要尽可能的挨着的原则摆放,找到所有从上往下看能看到的正方形。
分析:感觉这题比较复杂,是看了discuss和解题报告才AC了的。这题是转化为线段来做,直接将每个正方形的与X轴平行的角对角线作为处理对象。先确定线段的左右顶点,然后暴力扫描判断线段是否被遮挡。另外,因为该线段长度是根号二的倍数,为了避免小数的运算,可将线段长度扩大2倍,将边长乘以2即可。
代码:
POJ 2826 An Easy Problem?!
题意:由两块木板组成的装置,求能盛放的水量。
分析:显然没想象的那么简单,需要考虑的有很多。注意点:两条线不相交,左边或右边的口被遮住,交点是某条线的那个纵坐标较高的那点某条线段水平放置。
代码:
POJ 1039 Pipe
题意:有一宽度为1的折线管道,上面各顶点为(X0,Y0),(X1,Y1),……,(Xn,Yn),下面各顶点为(X0,Y0-1),(X1,Y1-1),……,(Xn,Yn-1),假设管壁都是不透明、不反射的,光线从左边入口处的(X0,Y0),(X0,Y0-1)之间射入,向四面八方直线传播,问光线最远能射到哪里(x坐标)或者能穿透整个管壁。
分析:本题上下顶点对于限制光线非常关键。解决方法:任取两个顶点,判断这两点所在直线是否能从入口射进到达该处,若能,则继续向后判断,看能否穿过其后的所有线段(Xi,Yi)(Xi,Yi-1),一旦与线段(Xk,Yk)(Xk,Yk-1)不相交,则交点必在前方,求交点。大概思路就这样,还算比较简洁。
代码:
POJ 3449 Geometric Shapes
题意:给一些几何图形,判断相交情况,按要求输出。
分析:题目不难,但很复杂,很烦。暴力枚举,只要注意输入输出就行。还有一个知识点,就是如何根据所给正方形(边不与轴平行)的两个对角线上的顶点,求另外两个点。
方法如下:
已知正方形的一对不相邻的顶点(x0,y0),(x2,y2),可以由方程组:
x1 + x3 = x0 + x2;
x1 - x3 = y2 - y0;
y1 + y3 = y0 + y2;
y3 - y1 = x2 - x0;
求得另一对不相邻的顶点(x1,y1),(x3,y3)。
代码:
POJ 1584 A Round Peg in a Ground Hole
题意:判断一个多边形是否为凸多边形,如果不是则输出”HOLE IS ILL-FORMED“,如果是则继续判断给定的一个圆是否在该凸多边形内,如果不在输出”PEG WILL NOT FIT“,否则输出”PEG WILL FIT“;
分析:判断是否为凸多边形,用向量叉积即可。判断圆是否在多边形内,先通过环顾法判断圆心是否在多边形内(环顾法黑书上有介绍),然后再判断是否圆心到各边的距离都大于半径。
代码:
POJ 2074 Line of Sight
题意:给出House和Property Line的位置,还有若干个障碍物的位置,求出在Property
Line上的最长的线段,满足在该线段上的所有的点都能看到完整的房子;若不存在这样的线段则输出“No View”。
分析:首先有个注意点说一下,障碍物可能不在house与Property
Line之间,得对输入数据进行过滤。然后,针对每个障碍物,求其在Property Line上可遮挡住的地方。实现方法就是求house.right与line.left(障碍物的左顶点)的所在直线与pl的交点;求house.left与line.right的所在直线与pl的交点。这样就可求得遮挡的地方(其实就是线段);再然后,求所有遮挡住的地方的交集;最后扫描一遍即可求得最大长度。
代码:
完毕。。。。
本篇所涉的题主要是与点,线,面,形基本关系以及点积叉积的理解相关的15道题,相对还是很基础的。但我这弱菜做的不太轻松。
POJ 2318 TOYS
题意:判断箱子每个块内有多少个玩具
分析:对于每个玩具的坐标,采用二分查找以确定玩具所在的块,其中玩具与分界(线段)的位置关系的判断可通过叉积来实现。
代码:
#include <stdio.h> #include <string.h> #define MAX 5010 struct Point { int x,y; }; struct Line { Point p1,p2; }line[MAX]; int m,n,x1,y1,x2,y2; int a[MAX]; Line makeline(int x1,int y1,int x2,int y2) { Line L; L.p1.x=x1; L.p1.y=y1; L.p2.x=x2; L.p2.y=y2; return L; } int direction(Point p1,Point p0,Point p2) { return (p1.x-p0.x)*(p2.y-p0.y)-(p1.y-p0.y)*(p2.x-p0.x); } bool isleft(Line l,Point p) { if(direction(l.p1,l.p2,p)>0)return true; else return false; } int binary_search(Point p)//二分查找 { int low,high,mid; low=0; high=n; while(low<=high) { mid=(low+high)/2; if(isleft(line[mid],p))high=mid-1; else low=mid+1; } return high; } int main() { int xx1,xx2,i,j; while(scanf("%d",&n)!=EOF&&n) { scanf("%d%d%d%d%d",&m,&x1,&y1,&x2,&y2); memset(a,0,sizeof(a)); line[0]=makeline(x1,y1,x1,y2); for(i=1;i<=n;i++) { scanf("%d%d",&xx1,&xx2); line[i]=makeline(xx1,y1,xx2,y2); } line[n+1]=makeline(x2,y1,x2,y2); Point p; for(i=1;i<=m;i++) { scanf("%d%d",&p.x,&p.y); a[binary_search(p)]++; } for(i=0;i<=n;i++) { printf("%d: %d\n",i,a[i]); } printf("\n"); } return 0; }
POJ 2398 Toy Storage
题意:与上一题一样,只是输出不同
代码:
#include <stdio.h> #include <vector> #include<algorithm> #include <string.h> using namespace std; #define MAX 5010 struct Point { int x,y; }; struct Line { Point p1,p2; }line[MAX]; struct Count { int data,num; }co; int m,n,x1,y1,x2,y2; int a[MAX],b[MAX]; bool Comp(Count c1,Count c2) { return c1.num>c2.num; } bool Comp1(Line l1,Line l2) { return l1.p1.x<l2.p1.x; } Line makeline(int x1,int y1,int x2,int y2) { Line L; L.p1.x=x1; L.p1.y=y1; L.p2.x=x2; L.p2.y=y2; return L; } int direction(Point p1,Point p0,Point p2) { return (p1.x-p0.x)*(p2.y-p0.y)-(p1.y-p0.y)*(p2.x-p0.x); } bool isleft(Line l,Point p) { if(direction(l.p1,l.p2,p)>0)return true; else return false; } int binary_search(Point p)//二分查找 { int low,high,mid; low=0; high=n; while(low<=high) { mid=(low+high)/2; if(isleft(line[mid],p))high=mid-1; else low=mid+1; } return high; } int main() { int xx1,xx2,i; while(scanf("%d",&n)!=EOF&&n) { scanf("%d%d%d%d%d",&m,&x1,&y1,&x2,&y2); memset(a,0,sizeof(a)); memset(b,0,sizeof(b)); line[0]=makeline(x1,y1,x1,y2); for(i=1;i<=n;i++) { scanf("%d%d",&xx1,&xx2); line[i]=makeline(xx1,y1,xx2,y2); } line[n+1]=makeline(x2,y1,x2,y2); sort(line,line+n+1,Comp1); Point p; for(i=1;i<=m;i++) { scanf("%d%d",&p.x,&p.y); a[binary_search(p)]++; } for(i=0;i<=n;i++) b[a[i]]++; printf("Box\n"); for(i=1;i<=m;i++) if(b[i]) printf("%d: %d\n",i,b[i]); } return 0; }
POJ 3304 Segment
题意:判断是否存在一条直线,使得n条线段在该直线上的投影存在公共部分。
分析:若存在这样一条直线,过投影相交区域作直线的垂线,该垂线必定与每条线段相交,问题转化为问是否存在一条线和所有线段相交;
若存在一条直线与所有线段相机相交,将该线旋转,平移,直到不能再动为止,此时该直线必定经过这些线段的某两个端点;
所以枚举任意两个端点即可,注意还要判重。(此思路是借鉴的别人的)
代码:
#include <stdio.h> #include<cmath> const double ESP=1e-8; const int MAXN=210; struct Point { double x,y; }point[MAXN]; int dblcmp(double d) { if(fabs(d) <ESP)return 0; else return d > 0 ? 1 : -1; } bool isEqual(double &a,double &b) { return fabs(a-b)<ESP; } double multi(Point p1, Point p2, Point p0) { return (p1.x - p0.x) * (p2.y - p0.y) - (p2.x - p0.x) * (p1.y - p0.y); } bool linecross(Point a,Point b,Point c,Point d)//过a,b的直线 { return dblcmp(multi(a,c,b))*dblcmp(multi(a,d,b))<=0; } int main() { bool isfind; int T,n; scanf("%d",&T); while(T--) { isfind=false; scanf("%d",&n); for(int i=1;i<=2*n;i+=2) scanf("%lf%lf%lf%lf",&point[i].x,&point[i].y,&point[i+1].x,&point[i+1].y); for(int i=1;i<=2*n&&!isfind;i++) for(int j=i+1;j<=2*n;j++) { if(isEqual(point[i].x,point[j].x)&&isEqual(point[i].y,point[j].y)) continue;//判重 int k; for(k=1;k<2*n;k+=2) { if(!linecross(point[i],point[j],point[k],point[k+1])) break; } if(k>=2*n){isfind=true;break;} } if(isfind)printf("Yes!\n"); else printf("No!\n"); } return 0; }
POJ 1269 Intersecting Lines
题意:直线相交判断(不相交、共线、相交),相交求交点
分析:没啥好分析的,略啦
代码:
#include <stdio.h> #include <cmath> const double ESP=1e-8; #define isequal(x,y)(fabs(x-y)<ESP) int dblcmp(double d) { if(fabs(d)<ESP) return 0; return (d>0)?1:-1; } struct Point { double x,y; }p[5]; struct Line { double a,b,c; }line[2]; Line lineFromSegment(Point p1, Point p2) { //线段所在直线,返回直线方程的三个系数 Line tmp; tmp.a = p2.y - p1.y; tmp.b = p1.x - p2.x; tmp.c = p2.x * p1.y - p1.x * p2.y; return tmp; } Point LineInter(Line l1, Line l2) { //求两直线得交点坐标 Point tmp; if(fabs(l1.b) < ESP){ tmp.x = -l1.c / l1.a; tmp.y = (-l2.c - l2.a * tmp.x) / l2.b; } else{ tmp.x = (l1.c * l2.b - l1.b * l2.c) / (l1.b * l2.a - l2.b * l1.a); tmp.y = (-l1.c - l1.a * tmp.x) / l1.b; } return tmp; } double multi(Point p1, Point p2, Point p0) { return (p1.x - p0.x) * (p2.y - p0.y) - (p2.x - p0.x) * (p1.y - p0.y); } int main() { int T; scanf("%d",&T); for(int i=0;i<T;i++) { scanf("%lf%lf%lf%lf%lf%lf%lf%lf",&p[0].x,&p[0].y,&p[1].x,&p[1].y,&p[2].x,&p[2].y,&p[3].x,&p[3].y); if(i==0)printf("INTERSECTING LINES OUTPUT\n"); line[0]=lineFromSegment(p[0],p[1]); line[1]=lineFromSegment(p[2],p[3]); if(isequal(line[0].a*line[1].b,line[0].b*line[1].a))//isequal(line[0].a/line[0].b,line[1].a/line[1].b)是wrong answer,因为浮点除法有误差 { if(!dblcmp(multi(p[0],p[1],p[2]))&&!dblcmp(multi(p[0],p[1],p[3])))//四点共线 printf("LINE\n"); else printf("NONE\n"); } else { p[4]=LineInter(line[0],line[1]); printf("POINT %.2lf %.2lf\n",p[4].x,p[4].y); } } printf("END OF OUTPUT\n"); return 0; }
POJ 1556 The Doors
题意:求从(0,5)到(10,5)的最短距离,之间有墙和门。
分析:黑书上的一道习题,个人觉得此题主要是Dijkstra算法的应用,其次是线段相交的判断。
代码:
#include <stdio.h> #include <math.h> #include <vector> using namespace std; struct Point { double x,y; }; struct Seg { Point a,b; }seg[60]; vector<double>data[21]; double min(double x,double y) {return x<y?x:y;} double max(double x,double y) {return x>y?x:y;} double multi(Point p1, Point p2, Point p0) { return (p1.x - p0.x) * (p2.y - p0.y) - (p2.x - p0.x) * (p1.y - p0.y); } bool isIntersected(double x1,double y1,double x2,double y2,double x3,double y3,double x4,double y4) { Point s1,e1,s2,e2; s1.x=x1;s1.y=y1; e1.x=x2;e1.y=y2; s2.x=x3;s2.y=y3; e2.x=x4;e2.y=y4; if( (max(s1.x, e1.x) >= min(s2.x, e2.x)) && (max(s2.x, e2.x) >= min(s1.x, e1.x)) && (max(s1.y, e1.y) >= min(s2.y, e2.y)) && (max(s2.y, e2.y) >= min(s1.y, e1.y)) && (multi(s2, e1, s1) * multi(e1, e2, s1) >0) && (multi(s1, e2, s2) * multi(e2, e1, s2) >0) ) return true; return false; } double distance(double ax,double ay,double bx,double by){ return sqrt((ax-bx)*(ax-bx)+(ay-by)*(ay-by)); } int fun(int x)//计算第x个墙的第一条线段的编号 { if(x==0)return 0; return (x-1)*3; } int main() { int n; double dist[21][4]; while(~scanf("%d",&n)&&n!=-1) { for(int i=0;i<21;i++)data[i].clear(); data[0].push_back(0); data[0].push_back(5.0); int num_seg=0; for(int i=1;i<=n;i++) { double hh; for(int j=0;j<5;j++) { scanf("%lf",&hh); data[i].push_back(hh); } seg[num_seg].a.x=seg[num_seg].b.x=data[i][0]; seg[num_seg].a.y=0;seg[num_seg].b.y=data[i][1]; seg[num_seg+1].a.x=seg[num_seg+1].b.x=data[i][0]; seg[num_seg+1].a.y=data[i][2];seg[num_seg+1].b.y=data[i][3]; seg[num_seg+2].a.x=seg[num_seg+2].b.x=data[i][0]; seg[num_seg+2].a.y=data[i][4];seg[num_seg+2].b.y=10.0; num_seg+=3; } data[n+1].push_back(10.0);data[n+1].push_back(5.0); for(int i=0;i<=n+1;i++) for(int j=0;j<4;j++) dist[i][j]=1000; dist[0][0]=0; for(int i=1;i<=n+1;i++) for(int j=1;j<data[i].size();j++) { for(int p=0;p<i;p++) for(int q=1;q<data[p].size();q++) { int k; for(k=fun(p);k<fun(i);k++)//亦可以 (k=0;k<num_seg;k++);当数据量很大时,前者效率高一点,但此题因数据少无所谓 { if(isIntersected(data[i][0],data[i][j],data[p][0],data[p][q],seg[k].a.x,seg[k].a.y,seg[k].b.x,seg[k].b.y)) break; } if(k==fun(i)) dist[i][j-1]=min(dist[i][j-1],dist[p][q-1]+distance(data[i][0],data[i][j],data[p][0],data[p][q])); } } printf("%.2lf\n",dist[n+1][0]); } return 0; }
POJ 2653 Pick-up sticks
题意:按顺序放置一定数量的枝条(线段),找到所有的不被压的枝条。
分析:针对每一个枝条,遍历在其后放的枝条,判断是否相交,若都不相交,则是符合条件的。
代码:
#include <stdio.h> #include <string.h> const int MAXN=100005; struct Point { double x,y; }; struct Seg { Point a,b; }seg[MAXN]; double min(double x,double y) {return x<y?x:y;} double max(double x,double y) {return x>y?x:y;} double multi(Point p1, Point p2, Point p0) { return (p1.x - p0.x) * (p2.y - p0.y) - (p2.x - p0.x) * (p1.y - p0.y); } bool isIntersected(Point s1, Point e1, Point s2, Point e2) { if( (max(s1.x, e1.x) >= min(s2.x, e2.x)) && (max(s2.x, e2.x) >= min(s1.x, e1.x)) && (max(s1.y, e1.y) >= min(s2.y, e2.y)) && (max(s2.y, e2.y) >= min(s1.y, e1.y)) && (multi(s2, e1, s1) * multi(e1, e2, s1) >= 0) && (multi(s1, e2, s2) * multi(e2, e1, s2) >= 0) ) return true; return false; } int mark[MAXN]; int main() { int n; while(scanf("%d",&n)!=EOF) { if(n==0)break; memset(mark,0,sizeof(mark)); for(int i=1;i<=n;i++) scanf("%lf%lf%lf%lf",&seg[i].a.x,&seg[i].a.y,&seg[i].b.x,&seg[i].b.y); for(int i=1;i<=n;i++) for(int j=i+1;j<=n;j++) { if(isIntersected(seg[i].a,seg[i].b,seg[j].a,seg[j].b)) {mark[i]=1;break;} } printf("Top sticks: "); int k; for(k=1;k<=n;k++) if(!mark[k]){printf("%d",k);break;} for(int i=k+1;i<=n;i++) if(!mark[i])printf(", %d",i); printf(".\n"); } return 0; }
POJ 1066 Treasure Hunt
题意:在一个矩形区域内,有n条线段,线段的端点是在矩形边上的有一个特殊点end,问从这个点到矩形边的最少经过的线段(实际穿过线段时只能穿过中点)
分析:首先要要理解穿过最少门的意思,其实只要枚举end与矩形边上每小段的中点mid连线与几条线段相交就OK了。
代码:
#include <stdio.h> #include <vector> #include <algorithm> using namespace std; struct Point { double x,y; }p,q[4]; struct Seg { Point a,b; }seg[31]; vector<Point>v[4]; bool Comp1(Point a,Point b) { return a.x<b.x; } bool Comp2(Point a,Point b) { return a.y<b.y; } bool Comp3(Point a,Point b) { return a.x>b.x; } bool Comp4(Point a,Point b) { return a.y>b.y; } void devide(Point po) { if(po.y==0)v[0].push_back(po); else if(po.x==100.0)v[1].push_back(po); else if(po.y==100.0)v[2].push_back(po); else v[3].push_back(po); } Point getmid(Point p1,Point p2) { Point temp; temp.x=(p1.x+p2.x)/2.0; temp.y=(p1.y+p2.y)/2.0; return temp; } double min(double x,double y) {return x<y?x:y;} double max(double x,double y) {return x>y?x:y;} double multi(Point p1, Point p2, Point p0) { return (p1.x - p0.x) * (p2.y - p0.y) - (p2.x - p0.x) * (p1.y - p0.y); } bool isIntersected(Point s1, Point e1, Point s2, Point e2) { if( (max(s1.x, e1.x) >= min(s2.x, e2.x)) && (max(s2.x, e2.x) >= min(s1.x, e1.x)) && (max(s1.y, e1.y) >= min(s2.y, e2.y)) && (max(s2.y, e2.y) >= min(s1.y, e1.y)) && (multi(s2, e1, s1) * multi(e1, e2, s1) >= 0) && (multi(s1, e2, s2) * multi(e2, e1, s2) >= 0) ) return true; return false; } int main() { int n; Point end; scanf("%d",&n); q[0].x=0;q[0].y=0; q[1].x=100.0;q[1].y=0; q[2].x=100.0;q[2].y=100.0; q[3].x=0;q[3].y=100.0; for(int i=0;i<4;i++) v[i].push_back(q[i]); for(int i=0;i<n;i++) { scanf("%lf%lf",&p.x,&p.y); devide(p); seg[i].a=p; scanf("%lf%lf",&p.x,&p.y); devide(p); seg[i].b=p; } scanf("%lf%lf",&end.x,&end.y); for(int i=0;i<3;i++) v[i].push_back(q[i+1]); v[3].push_back(q[0]); sort(v[0].begin(),v[0].end(),Comp1); sort(v[1].begin(),v[1].end(),Comp2); sort(v[2].begin(),v[2].end(),Comp3); sort(v[3].begin(),v[3].end(),Comp4); Point mid; Seg s; int big,now; big=30; for(int i=0;i<4;i++) { for(int j=0;j<v[i].size()-1;j++) { now=0; mid=getmid(v[i][j],v[i][j+1]); s.a=mid; s.b=end; for(int k=0;k<n;k++) { if(isIntersected(mid,end,seg[k].a,seg[k].b))now++; } if(now<big)big=now; } } printf("Number of doors = %d\n",big+1); return 0; }
POJ 1410 Intersection
题意:判断给定线段是否与矩形相交
分析:很简单的题,将线段与矩形的四条边一次比较即可。此题还需注意的有:(1)线段在矩形内也算相交,不然过不了;(2)给出的左上顶点和右下顶点不保证x1<x2,y1>y2;即需要自己判断
代码:
#include <stdio.h> struct Point { int x,y; }; struct Seg { Point a,b; }seg[5]; int xleft,xright,ybottom,ytop; Seg makeseg(int x1,int y1,int x2,int y2) { Seg temp; temp.a.x=x1; temp.a.y=y1; temp.b.x=x2; temp.b.y=y2; return temp; } int min(int x,int y) {return x<y?x:y;} int max(int x,int y) {return x>y?x:y;} double multi(Point p1, Point p2, Point p0) { return (p1.x - p0.x) * (p2.y - p0.y) - (p2.x - p0.x) * (p1.y - p0.y); } bool isIntersected(Point s1, Point e1, Point s2, Point e2) { if( (max(s1.x, e1.x) >= min(s2.x, e2.x)) && (max(s2.x, e2.x) >= min(s1.x, e1.x)) && (max(s1.y, e1.y) >= min(s2.y, e2.y)) && (max(s2.y, e2.y) >= min(s1.y, e1.y)) && (multi(s2, e1, s1) * multi(e1, e2, s1) >= 0) && (multi(s1, e2, s2) * multi(e2, e1, s2) >= 0) ) return true; return false; } bool inrectangle() { if((max(seg[0].a.x,seg[0].b.x)<xright)&& (min(seg[0].a.x,seg[0].b.x)>xleft)&& (max(seg[0].a.y,seg[0].b.y)<ytop)&& (min(seg[0].a.y,seg[0].b.y)>ybottom)) return true; return false; } int main() { int n; int flag; scanf("%d",&n); while(n--) { flag=0; int x1,y1,x2,y2; scanf("%d%d%d%d",&seg[0].a.x,&seg[0].a.y,&seg[0].b.x,&seg[0].b.y); scanf("%d%d%d%d",&x1,&y1,&x2,&y2); xleft=min(x1,x2); xright=max(x1,x2); ytop=max(y1,y2); ybottom=min(y1,y2); //scanf("%d%d%d%d",&xleft,&ytop,&xright,&ybottom); seg[1]=makeseg(xleft,ybottom,xright,ybottom); seg[2]=makeseg(xright,ybottom,xright,ytop); seg[3]=makeseg(xleft,ytop,xright,ytop); seg[4]=makeseg(xleft,ybottom,xleft,ytop); if(inrectangle())flag=1; else for(int i=1;i<=4;i++) { if(isIntersected(seg[0].a,seg[0].b,seg[i].a,seg[i].b)) { flag=1; break; } } if(flag)printf("T\n"); else printf("F\n"); } return 0; }
POJ 1696 Space Ant
题意:一只蚂蚁,只会向左转,现在给出平面上很多个点,求解一种走法,能使得蚂蚁能经过的点最多,每个顶点该蚂蚁只能经过一次,且所行走的路线不能发生交叉。
分析:这题考查了凸包的性质,是Graham算法的应用。先选取最左下方的(下的优先级比左高)点,然后对剩下的点进行极角排序,选取最小的;重复操作,直至所有的点都被选中输出。其实无论输入什么样的点集,一定可以走完全部n个点的,这是凸包的性质决定。
代码:
#include <stdio.h> #include<math.h> #include <algorithm> using namespace std; struct Point { int x,y,code; }; Point p[51]; int count1; int multi(Point p1, Point p2, Point p0) { return (p1.x - p0.x) * (p2.y - p0.y) - (p2.x - p0.x) * (p1.y - p0.y); } double Distance(Point a,Point b){ //若函数名为distance,则跟std::distance冲突了 return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y)*1.0); } bool Comp(Point a,Point b) { int temp=multi(a,b,p[count1]); if(temp>0)return true; else if(temp==0&&Distance(a,p[count1])<Distance(b,p[count1])) return true; return false; } void swap(Point &a,Point &b) { Point p1; p1=a; a=b; b=p1; } int main() { int T; int n; scanf("%d",&T); while(T--) { scanf("%d",&n); for(int i=1;i<=n;i++) { scanf("%d%d%d",&p[i].code,&p[i].x,&p[i].y); if(p[i].y<p[1].y)swap(p[1],p[i]); } printf("%d %d",n,p[1].code); count1=1; while(count1<n) { sort(p+count1+1,p+n+1,Comp); printf(" %d",p[count1+1].code); count1++; } printf("\n"); } return 0; }
POJ 3347 Kadj Squares
题意:给n个正方形,要求45°角放置,最左边的正方形紧贴Y轴,所有的正方形的下面的端点都在X轴上。然后按照正方形不能交错但要尽可能的挨着的原则摆放,找到所有从上往下看能看到的正方形。
分析:感觉这题比较复杂,是看了discuss和解题报告才AC了的。这题是转化为线段来做,直接将每个正方形的与X轴平行的角对角线作为处理对象。先确定线段的左右顶点,然后暴力扫描判断线段是否被遮挡。另外,因为该线段长度是根号二的倍数,为了避免小数的运算,可将线段长度扩大2倍,将边长乘以2即可。
代码:
#include <stdio.h> #include <cmath> struct Seg { int left,right,len; }seg[51]; int max(int x,int y) { if(x>y)return x; return y; } int main() { int n; while(~scanf("%d",&n)&&n) { for(int i=0;i<n;i++) { scanf("%d",&seg[i].len); seg[i].left=0; for(int j=0;j<i;j++) seg[i].left=max(seg[i].left,seg[j].right-abs(seg[i].len-seg[j].len)); seg[i].right=seg[i].left+(seg[i].len<<1); } for(int i=0;i<n;i++) { for(int j=0;j<i;j++) { if(seg[i].left<seg[i].right) { if(seg[i].left<seg[j].right) { if(seg[i].len<seg[j].len)seg[i].left=seg[j].right; else seg[j].right=seg[i].left; } } else break; } } int k; for(k=0;k<n;k++) if(seg[k].left < seg[k].right) { printf("%d",k+1);break;} for(int i = k+1; i < n; i++) { if(seg[i].left < seg[i].right) printf(" %d",i+1); } printf("\n"); } return 0; }
POJ 2826 An Easy Problem?!
题意:由两块木板组成的装置,求能盛放的水量。
分析:显然没想象的那么简单,需要考虑的有很多。注意点:两条线不相交,左边或右边的口被遮住,交点是某条线的那个纵坐标较高的那点某条线段水平放置。
代码:
#include <stdio.h> #include <cmath> #define ESP 1e-8 struct Point { double x,y; }p[4]; struct Line { double a,b,c; }line[2],l; Point getp(Point a,Point b,double y0) { if(y0==b.y)return b; double x0=fabs(a.x-(y0-a.y)*fabs((a.x-b.x))/(b.y-a.y)); Point temp; temp.x=x0; temp.y=y0; return temp; } double min(double x,double y) {return x<y?x:y;} double max(double x,double y) {return x>y?x:y;} double multi(Point p1, Point p2, Point p0) { return (p1.x - p0.x) * (p2.y - p0.y) - (p2.x - p0.x) * (p1.y - p0.y); } bool isIntersected(Point s1, Point e1, Point s2, Point e2) { //判断线段[s1, e1]和[s2, e2]是否相交 //1.快速排斥试验判断以两条线段为对角线的两个矩形是否相交 //2.跨立试验 if( (max(s1.x, e1.x) >= min(s2.x, e2.x)) && (max(s2.x, e2.x) >= min(s1.x, e1.x)) && (max(s1.y, e1.y) >= min(s2.y, e2.y)) && (max(s2.y, e2.y) >= min(s1.y, e1.y)) && (multi(s2, e1, s1) * multi(e1, e2, s1) >= 0) && (multi(s1, e2, s2) * multi(e2, e1, s2) >= 0) ) return true; return false; } Line lineFromSegment(Point p1, Point p2) { //线段所在直线,返回直线方程的三个系数 Line tmp; tmp.a = p2.y - p1.y; tmp.b = p1.x - p2.x; tmp.c = p2.x * p1.y - p1.x * p2.y; return tmp; } Point LineInter(Line l1, Line l2) { //求两直线得交点坐标 Point tmp; if(fabs(l1.b) < ESP){ tmp.x = -l1.c / l1.a; tmp.y = (-l2.c - l2.a * tmp.x) / l2.b; } else{ tmp.x = (l1.c * l2.b - l1.b * l2.c) / (l1.b * l2.a - l2.b * l1.a); tmp.y = (-l1.c - l1.a * tmp.x) / l1.b; } return tmp; } void swap(Point &a,Point &b) { Point temp; temp=a; a=b; b=temp; } int main() { int n; double s; scanf("%d",&n); int de=1; while(n--) { for(int i=0;i<4;i++) scanf("%lf%lf",&p[i].x,&p[i].y); //printf("Case %d:",de++); Point cross_point; if(!isIntersected(p[0],p[1],p[2],p[3])) printf("0.00\n"); else//相交 { line[0]=lineFromSegment(p[0],p[1]); line[1]=lineFromSegment(p[2],p[3]); cross_point=LineInter(line[0],line[1]); int num=0;//计算比交点高的点数 Point cp[2]; for(int i=0;i<4;i++) if(p[i].y>cross_point.y) cp[num++]=p[i]; if(num<=1)printf("0.00\n"); else { if(cp[0].y>cp[1].y)swap(cp[0],cp[1]); if((cp[0].x>cross_point.x&&cp[0].x<=cp[1].x&&multi(cp[1],cp[0],cross_point)<0)||(cp[0].x>=cp[1].x&&cp[0].x<cross_point.x&&multi(cp[1],cp[0],cross_point)>0)) printf("0.00\n"); else { Point p1,p2; p1.x=cp[0].x+1; p1.y=cp[0].y; line[0]=lineFromSegment(p1,cp[0]); line[1]=lineFromSegment(cross_point,cp[1]); p2=LineInter(line[0],line[1]); s=fabs(multi(p2,cp[0],cross_point))/2.0; printf("%.2lf\n",s); } } } } return 0; }
POJ 1039 Pipe
题意:有一宽度为1的折线管道,上面各顶点为(X0,Y0),(X1,Y1),……,(Xn,Yn),下面各顶点为(X0,Y0-1),(X1,Y1-1),……,(Xn,Yn-1),假设管壁都是不透明、不反射的,光线从左边入口处的(X0,Y0),(X0,Y0-1)之间射入,向四面八方直线传播,问光线最远能射到哪里(x坐标)或者能穿透整个管壁。
分析:本题上下顶点对于限制光线非常关键。解决方法:任取两个顶点,判断这两点所在直线是否能从入口射进到达该处,若能,则继续向后判断,看能否穿过其后的所有线段(Xi,Yi)(Xi,Yi-1),一旦与线段(Xk,Yk)(Xk,Yk-1)不相交,则交点必在前方,求交点。大概思路就这样,还算比较简洁。
代码:
#include <stdio.h> #include<cmath> #define ESP 1e-8 #define INF 99999 int dblcmp(double d) { if(fabs(d)<ESP) return 0; return (d>0)?1:-1; } struct Point { double x,y; }p[42]; struct Line { double a,b,c; }; Line lineFromSegment(Point p1, Point p2) { //线段所在直线,返回直线方程的三个系数 Line tmp; tmp.a = p2.y - p1.y; tmp.b = p1.x - p2.x; tmp.c = p2.x * p1.y - p1.x * p2.y; return tmp; } double cross(Point a,Point b,Point c) { return (b.x-a.x)*(c.y-a.y)-(c.x-a.x)*(b.y-a.y); } //判断直线ab和线段cd是否相交,相交为true,不相交为false bool linecross(Point a,Point b,Point c,Point d) { int d1,d2; d1=dblcmp(cross(a,c,b)); d2=dblcmp(cross(a,d,b)); if(d1*d2>0) return false; return true; } bool linecross1(Point a,Point b,Point c,Point d) { int d1,d2; d1=dblcmp(cross(a,c,b)); d2=dblcmp(cross(a,d,b)); if(d1*d2>=0) return false; return true; } Point LineInter(Point a,Point b,Point c,Point d) { //求两直线得交点坐标 Line l1,l2; l1=lineFromSegment(a,b); l2=lineFromSegment(c,d); Point tmp; if(fabs(l1.b) < ESP){ tmp.x = -l1.c / l1.a; tmp.y = (-l2.c - l2.a * tmp.x) / l2.b; } else{ tmp.x = (l1.c * l2.b - l1.b * l2.c) / (l1.b * l2.a - l2.b * l1.a); tmp.y = (-l1.c - l1.a * tmp.x) / l1.b; } return tmp; } int main() { int n; int flag; while(~scanf("%d",&n)&&n) { flag=0; for(int i=0,j=n;i<n;i++,j++) { scanf("%lf%lf",&p[i].x,&p[i].y); p[j].x=p[i].x; p[j].y=p[i].y-1; } double max=-1*INF ,now; for(int i=0;i<n;i++) { for(int j=n;j<2*n;j++) { if(i+n==j)continue; int k,rp=0,h; if(i>j-n)h=i; else h=j-n; for(k=0;k<h;k++) if(!linecross(p[i],p[j],p[k],p[k+n])){rp=1;break;} if(rp)continue;//该直线不可能从入口射进或射进但被挡住达不到i,j处 for(k=h+1;k<n;k++) { if(!linecross(p[i],p[j],p[k],p[k+n])) { if(linecross1(p[i],p[j],p[k-1],p[k])) { now=LineInter(p[i],p[j],p[k-1],p[k]).x; } else now=LineInter(p[i],p[j],p[k+n-1],p[k+n]).x; if(now>max)max=now; break; } } if(k==n){flag=1;break;} } if(flag)break; } if(flag)printf("Through all the pipe.\n"); else printf("%.2lf\n",max); } return 0; }
POJ 3449 Geometric Shapes
题意:给一些几何图形,判断相交情况,按要求输出。
分析:题目不难,但很复杂,很烦。暴力枚举,只要注意输入输出就行。还有一个知识点,就是如何根据所给正方形(边不与轴平行)的两个对角线上的顶点,求另外两个点。
方法如下:
已知正方形的一对不相邻的顶点(x0,y0),(x2,y2),可以由方程组:
x1 + x3 = x0 + x2;
x1 - x3 = y2 - y0;
y1 + y3 = y0 + y2;
y3 - y1 = x2 - x0;
求得另一对不相邻的顶点(x1,y1),(x3,y3)。
代码:
#include <stdio.h> #include <algorithm> #include <string.h> #include<vector> using namespace std; struct Point { double x,y; }; struct Shape { char label; int pn; Point p[20]; }shape[31]; vector<char>v[30]; Point input() { Point tmp; char c; while((c=getchar())!=')') { if(c=='(') scanf("%lf",&tmp.x); else if(c==',') scanf("%lf",&tmp.y); } return tmp; } bool comp(Shape s1,Shape s2) { return s1.label<s2.label; } double min(double x,double y) {return x<y?x:y;} double max(double x,double y) {return x>y?x:y;} double multi(Point p1, Point p2, Point p0) { return (p1.x - p0.x) * (p2.y - p0.y) - (p2.x - p0.x) * (p1.y - p0.y); } bool isintersected(Point s1, Point e1, Point s2,Point e2) { if( (max(s1.x, e1.x) >= min(s2.x, e2.x)) && (max(s2.x, e2.x) >= min(s1.x, e1.x)) && (max(s1.y, e1.y) >= min(s2.y, e2.y)) && (max(s2.y, e2.y) >= min(s1.y, e1.y)) && (multi(s2, e1, s1) * multi(e1, e2, s1) >= 0) && (multi(s1, e2, s2) * multi(e2, e1, s2) >= 0) ) return true; return false; } bool isintersect(Shape s1,Shape s2) { for(int i=0;i<s1.pn-1;i++) { int j; for(j=0;j<s2.pn-1;j++) if(isintersected(s1.p[i],s1.p[i+1],s2.p[j],s2.p[j+1])) return true; if(isintersected(s1.p[i],s1.p[i+1],s2.p[j],s2.p[0])) return true; } for(int i=0;i<s2.pn-1;i++) if(isintersected(s1.p[s1.pn-1],s1.p[0],s2.p[i],s2.p[i+1])) return true; if(isintersected(s1.p[s1.pn-1],s1.p[0],s2.p[s2.pn-1],s2.p[0])) return true; return false; } int main() { char c; char name[20]; int count=0; while(~scanf("%c",&c)&&c!='.') { if(c=='-') { sort(shape,shape+count,comp); for(int i=0;i<30;i++) v[i].clear(); for(int i=0;i<count;i++) { for(int j=i+1;j<count;j++) { if(isintersect(shape[i],shape[j])) { v[i].push_back(shape[j].label); v[j].push_back(shape[i].label); } } } for(int i=0;i<count;i++) { printf("%c ",shape[i].label); if(v[i].size()==0)printf("has no intersections\n"); else { printf("intersects with "); if(v[i].size()==1)printf("%c\n",v[i][0]); else if(v[i].size()==2) printf("%c and %c\n",v[i][0],v[i][1]); else { for(int j=0;j<v[i].size()-1;j++) printf("%c, ",v[i][j]); printf("and %c\n",v[i][v[i].size()-1]); } } } printf("\n"); count=0; } else if(c>='A'&&c<='Z') { shape[count].label=c; scanf("%s",name); if(!strcmp(name,"square")) { shape[count].pn=4; Point temp0,temp2; temp0=input(); temp2=input(); shape[count].p[0]=temp0; shape[count].p[2]=temp2; shape[count].p[1].x=(temp0.x+temp2.x+temp2.y-temp0.y)/2.0; shape[count].p[1].y=(temp0.y+temp2.y-temp2.x+temp0.x)/2.0; shape[count].p[3].x=temp0.x+temp2.x-shape[count].p[1].x; shape[count].p[3].y=temp2.x-temp0.x+shape[count].p[1].y; } else if(!strcmp(name,"line")) { shape[count].pn=2; shape[count].p[0]=input(); shape[count].p[1]=input(); } else if(!strcmp(name,"rectangle")) { shape[count].pn=4; shape[count].p[0]=input(); shape[count].p[1]=input(); shape[count].p[2]=input(); shape[count].p[3].x=shape[count].p[0].x+shape[count].p[2].x-shape[count].p[1].x; shape[count].p[3].y=shape[count].p[0].y+shape[count].p[2].y-shape[count].p[1].y; } else if(!strcmp(name,"triangle")) { shape[count].pn=3; shape[count].p[0]=input(); shape[count].p[1]=input(); shape[count].p[2]=input(); } else// if(name=="polygon") { scanf("%d",&shape[count].pn); for(int i=0;i<shape[count].pn;i++) shape[count].p[i]=input(); } count++; } } return 0; }
POJ 1584 A Round Peg in a Ground Hole
题意:判断一个多边形是否为凸多边形,如果不是则输出”HOLE IS ILL-FORMED“,如果是则继续判断给定的一个圆是否在该凸多边形内,如果不在输出”PEG WILL NOT FIT“,否则输出”PEG WILL FIT“;
分析:判断是否为凸多边形,用向量叉积即可。判断圆是否在多边形内,先通过环顾法判断圆心是否在多边形内(环顾法黑书上有介绍),然后再判断是否圆心到各边的距离都大于半径。
代码:
#include <stdio.h> #include <cmath> const double ESP=1e-8; const double pi=3.141592654; struct Point { double x,y; }p[100]; struct Line { double a,b,c; }; int dblcmp(double d) { if(fabs(d)<ESP) return 0; return (d>0)?1:-1; } Line lineFromSegment(Point p1, Point p2) { //线段所在直线,返回直线方程的三个系数 Line tmp; tmp.a = p2.y - p1.y; tmp.b = p1.x - p2.x; tmp.c = p2.x * p1.y - p1.x * p2.y; return tmp; } int n; double cx,cy,cr; double multi(Point a,Point b,Point c)//连续三点 { return (b.x-a.x)*(c.y-b.y)-(c.x-b.x)*(b.y-a.y); } double pointmulti(Point a,Point b,Point c)//点积ab*ac { return (b.x-a.x)*(c.x-a.x)+(b.y-a.y)*(c.y-a.y); } bool isill_formed()//判断是否为凹的 { double dirction=multi(p[0],p[1],p[2]); for(int i=1;i<=n-3;i++) if(multi(p[i],p[i+1],p[i+2])*dirction<0) return true; if(multi(p[n-2],p[n-1],p[0])*dirction<0|| multi(p[n-1],p[0],p[1])*dirction<0) return true; return false; } double dis(double cx,double cy,Point a,Point b)//圆心(cx,cy)到线段a,b的距离 { Line l=lineFromSegment(a,b); double dist; dist=abs(l.a*cx+l.b*cy+l.c)/sqrt(l.a*l.a+l.b*l.b); return dist; } double dis1(double cx,double cy,Point p)//圆心到顶点的距离 { return sqrt((p.x-cx)*(p.x-cx)+(p.y-cy)*(p.y-cy)); } bool iscir_in_pol() { double total=0; Point cp; cp.x=cx;cp.y=cy; for(int i=0;i<n-1;i++)//环顾法判断圆心是否在多边形内 total+=acos(pointmulti(cp,p[i],p[i+1])/(dis1(cx,cy,p[i])*dis1(cx,cy,p[i+1]))); total+=acos(pointmulti(cp,p[n-1],p[0])/(dis1(cx,cy,p[n-1])*dis1(cx,cy,p[0]))); if(dblcmp(total-2*pi)!=0)return false; for(int i=0;i<n-1;i++)//圆心到各边的距离满足条件 { if(dis(cx,cy,p[i],p[i+1])<cr)return false; } if(dis(cx,cy,p[0],p[n-1])<cr)return false; return true; } int main() { while(~scanf("%d",&n)&&n>2) { scanf("%lf%lf%lf",&cr,&cx,&cy); for(int i=0;i<n;i++) { scanf("%lf%lf",&p[i].x,&p[i].y); } if(isill_formed())printf("HOLE IS ILL-FORMED\n"); else { if(!iscir_in_pol())printf("PEG WILL NOT FIT\n"); else printf("PEG WILL FIT\n"); } } return 0; }
POJ 2074 Line of Sight
题意:给出House和Property Line的位置,还有若干个障碍物的位置,求出在Property
Line上的最长的线段,满足在该线段上的所有的点都能看到完整的房子;若不存在这样的线段则输出“No View”。
分析:首先有个注意点说一下,障碍物可能不在house与Property
Line之间,得对输入数据进行过滤。然后,针对每个障碍物,求其在Property Line上可遮挡住的地方。实现方法就是求house.right与line.left(障碍物的左顶点)的所在直线与pl的交点;求house.left与line.right的所在直线与pl的交点。这样就可求得遮挡的地方(其实就是线段);再然后,求所有遮挡住的地方的交集;最后扫描一遍即可求得最大长度。
代码:
#include<stdio.h> #include <vector> #include<cmath> #include <algorithm> #define ESP 1e-8 using namespace std; int dblcmp(double d) { if(fabs(d)<ESP) return 0; return (d>0)?1:-1; } struct Point { double x,y; }; struct Object { Point left,right; }house,pl,line; struct Line { double a,b,c; }; struct Seg { double xl,xr; }seg; Line lineFromSegment(Point p1, Point p2) { //线段所在直线,返回直线方程的三个系数 Line tmp; tmp.a = p2.y - p1.y; tmp.b = p1.x - p2.x; tmp.c = p2.x * p1.y - p1.x * p2.y; return tmp; } double LineInter(Point a,Point b,Point c,Point d) { //求两直线得交点坐标 Line l1=lineFromSegment(a,b); Line l2=lineFromSegment(c,d); Point tmp; if(fabs(l1.b) < ESP){ tmp.x = -l1.c / l1.a; //tmp.y = (-l2.c - l2.a * tmp.x) / l2.b; } else{ tmp.x = (l1.c * l2.b - l1.b * l2.c) / (l1.b * l2.a - l2.b * l1.a); //tmp.y = (-l1.c - l1.a * tmp.x) / l1.b; } return tmp.x; } //计算a,b,c三点的叉积,判断a,b,c三点的位置关系 double cross(Point a,Point b,Point c) { return (b.x-a.x)*(c.y-a.y)-(c.x-a.x)*(b.y-a.y); } //判断直线ab和线段cd是否相交,相交为true,不相交为false bool linecross(Point a,Point b,Point c,Point d) { int d1,d2; d1=dblcmp(cross(a,c,b)); d2=dblcmp(cross(a,d,b)); if(d1*d2>0) return false; return true; } vector<Seg>v; bool comp(Seg s1,Seg s2) { return s1.xl<s2.xl; } bool isbetween(double yy) { if((yy>house.left.y&&yy<pl.left.y)||(yy<house.left.y&&yy>pl.left.y)) return true; return false; } int main() { double x1,x2,y; int n; while(~scanf("%lf%lf%lf",&x1,&x2,&y)) { if(x1==0&&x2==0&&y==0)break; house.left.x=x1; house.right.x=x2; house.right.y=house.left.y=y; scanf("%lf%lf%lf",&pl.left.x,&pl.right.x,&pl.left.y); pl.right.y=pl.left.y; scanf("%d",&n); for(int i=0;i<n;i++) { scanf("%lf%lf%lf",&line.left.x,&line.right.x,&line.left.y); line.right.y=line.left.y; if(!isbetween(line.right.y))//预处理 {i--;n--;} else { seg.xl=LineInter(house.right,line.left,pl.left,pl.right); if(seg.xl>=pl.right.x){i--;n--;continue;} else if(seg.xl<pl.left.x) seg.xl=pl.left.x; seg.xr=LineInter(house.left,line.right,pl.left,pl.right); if(seg.xr<=pl.left.x){i--;n--;continue;} else if(seg.xr>pl.right.x) seg.xr=pl.right.x; v.push_back(seg); } } //求集合 double max=0.0; if(v.size()>0) { double length=0,sx,ex; sx=ex=pl.left.x; sort(v.begin(),v.end(),comp); for(int i=0;i<v.size();i++) { if(v[i].xl>ex) { length=v[i].xl-ex; if(length>max)max=length; sx=v[i].xl; ex=v[i].xr; } else if(v[i].xr>ex) ex=v[i].xr; } length=pl.right.x-ex; if(length>max)max=length; } else max=pl.right.x-pl.left.x; if(max>0)printf("%.2lf\n",max); else printf("No View\n"); v.clear(); } return 0; }
完毕。。。。
相关文章推荐
- 计算几何入门题#1(点,线基本关系,点积叉积的理解)
- 计算几何小结 我对计算几何的理解以及叉积和点积
- POJ 2398 Toy Storage(计算几何,叉积判断点和线段的关系)
- 7月10号 计算几何 对向量叉积 判断两条直线是否相交的理解
- 向量的叉积和点积的 几何意义 有关于投影的推导(和点积的关系)
- POJ 2318 TOYS 计算几何 入门题 叉积 + 二分
- POJ--2318 -- TOYS [点、线基本关系] [计算几何]
- 关于关系代数中除法的理解以及如何用基本运算表示除法
- POJ 2318 TOYS 计算几何 入门题 叉积 + 二分
- POJ 2398 Toy Storage(计算几何,叉积判断点和线段的关系)
- [您有新的未分配科技点]计算几何入门(1):点,向量以及向量的简单应用
- [POJ2653]Pick-up sticks(计算几何-叉积)
- java中八种基本数据类型以及它们的封装类,String类型的一些理解
- POJ 2826 An Easy Problem?! --计算几何,叉积
- 熟悉RIP的基本配置,理解RIP的工作原理工作过程,以及RIP中路由表的学习过程。
- ERP流程入门_从会计分录理解企业基本流程
- Android入门开发之常用的adb指令以及AndroidStudio基本配置(五)
- 线程的基本概念、线程的基本状态以及状态之间的关系
- 数据库启动的过程以及动态性能表的基本理解
- HDU4793 2013 长沙 C (计算几何—点和圆的位置关系—解法①列方程求解[时间作自变量] —解法②向量积和sin角度求解长度再除以有方向的速度)