很多题,很多代码: 一、点,线,面,形基本关系,点积叉积的理解 /*poj2318toys*/ //判断箱子每一个块内有多少个玩具,可以用叉积的性质找到玩具的位置,过程采用二分查找。 #include <cstdio> #include <cstring> using namespace std; #define EPS 1e-8 const int MAXN = 5010; struct Point{ double x,y; Point(){} Point(double _x,double _y):x(_x),y(_y){} void input(){ scanf("%lf%lf",&x,&y); } }; inline double difcross(Point p1,Point p0,Point p2){ return (p1.x-p0.x)*(p2.y-p0.y)-(p2.x-p0.x)*(p1.y-p0.y); } struct pi{ Point first; Point second; }PII[MAXN]; int mark[MAXN]; int n,m; double x1,y1,x2,y2; int main(){ int k = 0; while(scanf("%d",&n) != EOF){ if(n == 0)break; k ++; if(k != 1)putchar('\n'); scanf("%d%lf%lf%lf%lf",&m,&x1,&y1,&x2,&y2); memset(mark,0,sizeof(mark)); double ui,li; for(int i = 1; i <= n; ++i){ scanf("%lf%lf",&ui,&li); PII[i].first = Point(ui,y1); PII[i].second = Point(li,y2); } Point toy; for(int i = 0; i < m; ++i){ toy.input(); int low = 1,high = n,mid; while(low <= high){ mid = (low + high)/2; if(difcross(toy,PII[mid].second,PII[mid].first) > 0) low = mid + 1; else high = mid - 1; } //printf("low = %d high = %d mid = %d\n",low,high,mid); mark[high] ++; } for(int i = 0; i <= n; ++i) printf("%d: %d\n",i,mark[i]); } } //另外,poj2398Toy Storage与此题雷同,不再重复 /*POJ3304 Segments*/ // 判断线段与直线相交 #include<iostream> #include<cmath> using namespace std; #define ESP 1e-8 inline int dblcmp(double d){ if(fabs(d) < ESP)return 0; else return d > 0 ? 1 : -1; } struct Point{ double x,y; }; struct Seg{ Point a,b; }; struct xlg{ double x,y; }; inline double pdis(Point a,Point b){ return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y)); } inline double difpro(Point a,Point b,Point c){ double x1 = b.x - a.x, y1 = b.y - a.y, x2 = c.x - a.x, y2 = c.y - a.y; return (x1*y2 - x2*y1); } inline int seg_line_intersect(Seg seg, Point l1,Point l2){ if(dblcmp(difpro(l1,seg.a,l2)*difpro(l1,seg.b,l2)) <= 0)return 1; return 0; } const int maxn = 110; Seg seg[maxn]; int n; inline bool cal(Point l1,Point l2){ for(int i = 0; i < n; i++){ if(!seg_line_intersect(seg[i],l1,l2)) return 0; } return 1; } int main(){ int cas,i,j; double x,y; scanf("%d",&cas); while(cas--){ int flag = 0; scanf("%d",&n); for(i = 0; 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(i = 0; i < n; i++){ for(j = i; j < n; j++){ if(dblcmp(pdis(seg[i].a,seg[j].a)) > 0){ if(cal(seg[i].a,seg[j].a)){ flag = 1;break; } } if(dblcmp(pdis(seg[i].a,seg[j].b)) > 0){ if(cal(seg[i].a,seg[j].b)){ flag = 1;break; } } if(dblcmp(pdis(seg[i].b,seg[j].a)) > 0){ if(cal(seg[i].b,seg[j].a)){ flag = 1;break; } } if(dblcmp(pdis(seg[i].b,seg[j].b)) > 0){ if(cal(seg[i].b,seg[j].b)){ flag = 1;break; } } } } if(flag)printf("Yes!\n"); else printf("No!\n"); } return 0; } /*poj1269Intersecting Lines*/ //直线相交判断,注意是一条直线(共线)的情况 #include <cstdio> #include <cstring> #include <cmath> using namespace std; #define feq(a,b) (fabs((a)-(b))<EPS) #define EPS 1e-8 struct Point{ double x,y; Point(){} Point(double _x,double _y):x(_x),y(_y){} void input(){ scanf("%lf%lf",&x,&y); } }; struct Line{ double a,b,c; }; inline void getline(Point p1,Point p2,Line &l){ l.a = p2.y - p1.y; l.b = p1.x - p2.x; l.c = p1.y*p2.x - p1.x*p2.y; if (l.a < 0) l.a *= -1,l.b *= -1,l.c *= -1; } inline int line_intersect(Line l1,Line l2,Point &ans){ double d=l1.a*l2.b-l2.a*l1.b; if (feq(d, 0)) return 0; ans.x = (l2.c*l1.b-l1.c*l2.b)/d; ans.y = (l2.a*l1.c-l1.a*l2.c)/d; return 1; } int N; int main(){ scanf("%d",&N); Point p3,p4,q1,q2,ans; Line l1,l2; puts("INTERSECTING LINES OUTPUT"); while(N --){ p3.input(); p4.input(); getline(p3,p4,l1); q1.input(); q2.input(); getline(q1,q2,l2); int tmp = line_intersect(l1,l2,ans); if(tmp == 0){ if(feq(l1.a*l2.b,l2.a*l1.b) && feq(l1.a*l2.c,l2.a*l1.c) && feq(l1.b*l2.c,l2.b*l1.c)){ printf("LINE\n"); } else printf("NONE\n"); } else printf("POINT %.2lf %.2lf\n",ans.x,ans.y); } puts("END OF OUTPUT"); return 0; } /*poj1556The Doors*/ // 利用的计算几何并不多(判断线段相交),建图比较繁琐,然后用dijkstra求最短路即可 #include <cstdio> #include <cstring> #include<cmath> using namespace std; #define inf 99999999 const int maxn = 200; struct Point { double x,y; Point(){} Point(double _x,double _y):x(_x),y(_y){} }; double cross(Point a,Point a1,Point a2){ return (a1.x - a.x)*(a2.y - a.y)-(a2.x - a.x)*(a1.y - a.y); } double dist[maxn][maxn]; double pdis(Point a,Point b){ return sqrt( (a.x - b.x)*(a.x - b.x)+(a.y - b.y)*(a.y - b.y) ); } int isintersect(Point a1,Point a2,Point b1,Point b2){ if(cross(a1,a2,b1)*cross(a1,a2,b2) < 0 && cross(b1,b2,a1)*cross(b1,b2,a2) < 0)return 1; return 0; } Point points[maxn]; int main(){ int n,i,j; while(scanf("%d",&n) != EOF){ if(n == -1)break; int cnt = 1; double num,x[maxn]; points[0] = Point(0,5); for(i = 1; i <= n; i ++){ scanf("%lf",&x[i]); for(j = 0; j < 4; j++){ scanf("%lf",&num); points[cnt++] = Point(x[i],num); } } points[cnt] = Point(10,5); int ti,fi,tj,fj; for(i = 0; i < maxn; i++){ for(j = 0; j < maxn ; j++){ dist[i][j] = inf; } } for(i = 0; i < maxn; i++)dist[i][i] = 0; for(i = 0; i <= cnt; i++){ for(j = i+1; j <= cnt; j++){ if(points[i].x == points[j].x){ continue; } if(i%4 == 0)ti = i/4; else ti = i/4+1; if(j%4 == 0)tj = j/4; else tj = j/4+1; int flag = 1; for(int k= ti + 1; k < tj; k++){ Point pk1 = Point(x[k],0); Point pk2 = Point(x[k],10); if(isintersect(points[i],points[j],pk1,points[4*(k-1)+1])){ flag = 0;break; } if(isintersect(points[i],points[j],points[4*(k-1)+2],points[4*(k-1)+3])){ flag = 0;break; } if(isintersect(points[i],points[j],points[4*(k-1)+4],pk2)){ flag = 0; break; } } if(flag){ double tm = pdis(points[i],points[j]); dist[i][j] = tm; dist[j][i] = tm; } } } cnt++; int mark[maxn]; double dis[maxn]; for(i = 0; i < cnt; i++){ dis[i] = dist[0][i]; } memset(mark,0,sizeof(mark)); mark[0] = 1; for(i = 0; i < cnt - 1; i++){ double mi = inf; int u = 0; for(j = 0; j < cnt; j++){ if(!mark[j] && dis[j] < mi){ mi = dis[j]; u = j; } } mark[u] = 1; for(j = 0; j < cnt; j++){ if(!mark[j] && dis[u] + dist[u][j] < dis[j]){ dis[j] = dis[u] + dist[u][j]; } } } printf("%.2lf\n",dis[cnt-1]); } return 0; } /*poj2653Pick-up sticks*/ //赤裸裸的线段求交 #include <cstdio> #include <cstring> #include <cmath> using namespace std; using namespace std; #define EPS 1e-6 #define INF 1000000000 const int maxn = 100000; struct Point { double x,y; Point(){}; Point(double _x,double _y):x(_x),y(_y){} void in(){ scanf("%lf%lf",&x,&y); } }; double min(double a,double b){return a > b ? b : a;} double max(double a,double b){return a > b ? a : b;} double pdis(Point a,Point b){ return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y)); } double cproduct(Point a,Point a1,Point a2){ return (a1.x - a.x)*(a2.y - a.y) -(a2.x - a.x)*(a1.y - a.y); } double dproduct(Point a,Point a1,Point a2){ return (a1.x-a.x)*(a1.y-a.y) + (a2.x-a.x)*(a2.y-a.y); } bool isIntersected(Point s1, Point e1, Point s2, Point e2) { return ( 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) ) & ( cproduct(s2, e1, s1) * cproduct(e1, e2, s1)>0) //>0规范性相交且不包括重合; & ( cproduct(s1, e2, s2) * cproduct(e2, e1, s2)>0); //>=0包括规范性和非规范性相交且包括重合; } struct seg{ Point a,b; }; int main(){ int n; seg segs[maxn]; while(scanf("%d",&n)!=EOF){ if(n == 0)break; for(int i = 0; i < n; i++){ scanf("%lf%lf%lf%lf",&segs[i].a.x,&segs[i].a.y,&segs[i].b.x,&segs[i].b.y); } int mark[maxn]; memset(mark,0,sizeof(mark)); for(int i = 0; i < n; i++){ for(int j = i+1; j < n; j++){ if(isIntersected(segs[i].a,segs[i].b,segs[j].a,segs[j].b) != 0){ mark[i] = 1; break; } } } printf("Top sticks: "); int ans[maxn]; int q = -1; for(int i = 0; i < n; i++){ if(mark[i] == 0)ans[++q] = i+1; } for(int i = 0; i < q; i++){ printf("%d, ",ans[i]); } printf("%d.\n",ans[q]); } return 0; } /*POJ 1066 Treasure Hunt*/ //线段相交判断 #include<iostream> #include<algorithm> #include<cmath> using namespace std; #define ESP 1e-8 int dblcmp(double d){ if(fabs(d) < ESP)return 0; else return d > 0 ? 1 : -1; } struct Point{ double x,y; }; struct Seg{ Point a,b; }; struct xlg{ double x,y; }; double difpro(xlg a,xlg b){ return (a.x*b.y-a.y*b.x); } xlg getxlg(Point a,Point b){ xlg tmp; tmp.x = b.x - a.x; tmp.y = b.y - a.y; return tmp; } int seg_line_intersect(Point a,Point b, Point l1,Point l2) { xlg v1 = getxlg(l1,a), v2 = getxlg(l1,l2), v3 = getxlg(l1,b); if(dblcmp(difpro(v1,v2)*difpro(v3,v2)) < 0)return 1; return 0; } const int maxn = 35; Seg segs[maxn]; Point dest; int n; int main(){ double y0[maxn],x0[maxn],y100[maxn],x100[maxn]; while(scanf("%d",&n)!=EOF){ memset(y0,0,sizeof(y0)); memset(x0,0,sizeof(x0)); memset(y100,0,sizeof(y100)); memset(x100,0,sizeof(x100)); int qy0 = 1,qx0 = 1, qx100 = 1,qy100 = 1; for(int i = 0; i < n; i++){ scanf("%lf%lf%lf%lf",&segs[i].a.x,&segs[i].a.y,&segs[i].b.x,&segs[i].b.y); if(segs[i].a.x == 0)x0[qx0++] = segs[i].a.y; if(segs[i].a.x == 100)x100[qx100++] = segs[i].a.y; if(segs[i].a.y == 0)y0[qy0++] = segs[i].a.x; if(segs[i].a.y == 100)y100[qy100++] = segs[i].a.x; if(segs[i].b.x == 0)x0[qx0++] = segs[i].b.y; if(segs[i].b.x == 100)x100[qx100++] = segs[i].b.y; if(segs[i].b.y == 0)y0[qy0++] = segs[i].b.x; if(segs[i].b.y == 100)y100[qy100++] = segs[i].b.x; } int cnt,mi = 9999999; scanf("%lf%lf",&dest.x,&dest.y); if(n == 0){ printf("Number of doors = 1\n"); continue; } sort(x0,x0+qx0); sort(y0,y0+qy0); sort(x100,x100+qx100); sort(y100,y100+qy100); x0[0] = 0;x0[qx0] = 100; y0[0] = 0;y0[qy0] = 100; x100[0] = 0;x100[qx100] = 100; y100[0] = 0; y100[qy100] = 100; for(int i = 1; i <= qx0; i++){ cnt = 1; Point t; t.y = (x0[i-1]+x0[i])/2; t.x = 0; for(int j = 0; j < n; j++){ if(seg_line_intersect(t,dest,segs[j].a,segs[j].b))cnt++; } if(mi > cnt)mi = cnt; } for(int i = 1; i <= qx100; i++){ cnt = 1; Point t; t.y = (x100[i-1]+x100[i])/2; t.x = 100; for(int j = 0; j < n; j++){ if(seg_line_intersect(t,dest,segs[j].a,segs[j].b))cnt++; } if(mi > cnt)mi = cnt; } for(int i = 1; i <= qy0; i++){ cnt = 1; Point t; t.x = (y0[i-1]+y0[i])/2; t.y = 0; for(int j = 0; j < n; j++){ if(seg_line_intersect(t,dest,segs[j].a,segs[j].b))cnt++; } if(mi > cnt)mi = cnt; } for(int i = 1; i <= qy100; i++){ cnt = 1; Point t; t.x = (y100[i-1]+y100[i])/2; t.y = 100; for(int j = 0; j < n; j++){ if(seg_line_intersect(t,dest,segs[j].a,segs[j].b))cnt++; } if(mi > cnt)mi = cnt; } printf("Number of doors = %d\n",mi); } return 0; } /*POJ 1410 Intersection*/ //判断线段是否与矩形相交,分别判断线段是否与矩形的四条边相交,另外注意一下整个线段在矩形中即可,还有这题描述不清,看discuss吧; #include <cstdio> #include <cstring> #include <cmath> using namespace std; #define EPS 1e-8 #define sqr(a) ( (a*a) ) #define max(a,b) ((a)>(b) ? (a) : (b)) #define min(a,b) ((a)<(b) ? (a) : (b)) #define feq(a,b) (fabs((a)-(b))<EPS)//a==b #define fbg(a,b) ((a) > EPS+(b)) //a > b #define fsm(a,b) ((b) > EPS+(a)) //a < b #define fbgeq(a,b) ((a) >= (b)-EPS) //a >= b #define fsmeq(a,b) ((b) >= (a)-EPS) //a <= b struct Point{ double x,y; Point(){} Point(double _x,double _y):x(_x),y(_y){} void input(){ scanf("%lf%lf",&x,&y); } }; struct Segment{ Point a,b; Segment(){} Segment(Point _a,Point _b):a(_a),b(_b){} }; inline double difcross(Point p0,Point p1,Point p2){ return (p1.x-p0.x)*(p2.y-p0.y)-(p2.x-p0.x)*(p1.y-p0.y); } inline bool SegIntersect(Segment s1,Segment s2) { double mxs1x = max(s1.a.x,s1.b.x), mns1x = min(s1.a.x,s1.b.x); double mxs2x = max(s2.a.x,s2.b.x), mns2x = min(s2.a.x,s2.b.x); double mxs1y = max(s1.a.y,s1.b.y), mns1y = min(s1.a.y,s1.b.y); double mxs2y = max(s2.a.y,s2.b.y), mns2y = min(s2.a.y,s2.b.y); return fsmeq(difcross(s1.a,s1.b,s2.a)*difcross(s1.a,s1.b,s2.b), 0)&& fsmeq(difcross(s2.a,s2.b,s1.a)*difcross(s2.a,s2.b,s1.b), 0)&& fbgeq(mxs1x, mns2x)&&fbgeq(mxs2x, mns1x) && fbgeq(mxs1y, mns2y)&&fbgeq(mxs2y, mns1y); } Point s,t,p1,p2,p3,p4; Segment s1,s2; int main(){ int n; scanf("%d",&n); while(n --){ s.input(); t.input(); p1.input(); p3.input(); double maxx = max(p1.x,p3.x); double minx = min(p1.x,p3.x); double maxy = max(p1.y,p3.y); double miny = min(p1.y,p3.y); p1 = Point(minx,maxy); p3 = Point(maxx,miny); p2 = Point(p1.x,p3.y); p4 = Point(p3.x,p1.y); s1 = Segment(s,t); maxx = max(s.x,t.x); minx = min(s.x,t.x); maxy = max(s.y,t.y); miny = min(s.y,t.y); bool flag = 0; if(minx > p1.x + EPS && maxx +EPS < p3.x && maxy +EPS < p1.y && miny > p3.y+EPS)flag = 1; s2 = Segment(p1,p2); if(SegIntersect(s1,s2))flag = 1; s2 = Segment(p2,p3); if(SegIntersect(s1,s2))flag = 1; s2 = Segment(p3,p4); if(SegIntersect(s1,s2))flag = 1; s2 = Segment(p4,p1); if(SegIntersect(s1,s2))flag = 1; if(!flag)puts("F"); else puts("T"); } return 0; } /*POJ 1696 Space Ant*/ //非常好的题目,知道怎么做的话就是个水题,根据Graham求凸包的思想,每次找到最左下的那个点即可(每次排序的基准点改变) #include <cstdio> #include <cstring> #include <cmath> #include <algorithm> using namespace std; #define EPS 1e-8 #define feq(a,b) (fabs((a)-(b))<EPS) #define fbg(a,b) ((a) > EPS+(b)) #define dis(a, b) ((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y)) #define dist(p1, p2, a) (fabs(difcross(p1, a, p2)/sqrt(dis(p1,p2)))) const int MAXN = 55; struct Point{ double x,y; int id; Point(){} Point(double _x,double _y):x(_x),y(_y){} void input(){ scanf("%d%lf%lf",&id,&x,&y); } }; inline double difcross(Point a,Point b,Point c){ return (b.x-a.x)*(c.y-a.y)-(c.x-a.x)*(b.y-a.y); } inline double pdis(Point a,Point b){ return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y)); } Point p[MAXN]; Point p0; int anstop,n,ans[MAXN]; inline int cmp(Point a, Point b) { double k = difcross(p0, a, b); if(feq(k,0) && fbg(pdis(a, p0) , pdis(b, p0)))return 1; else if( k > EPS ) return 1; return 0; } int main(){ int cas; scanf("%d",&cas); while(cas --){ scanf("%d",&n); for(int i = 0; i < n ; ++i){ p[i].input(); if(p[i].y < p[0].y) swap(p[0],p[i]); } anstop = 0; int cur = 0; p0 = p[cur]; ans[anstop++] = p[cur++].id; for(int i = 0; i < n - 1; ++i){ sort(p+cur,p+n,cmp); p0 = p[cur]; ans[anstop++] = p[cur++].id; } printf("%d",anstop); for(int i = 0; i < anstop; ++i){ printf(" %d",ans[i]); } printf("\n"); } return 0; } poj3347Kadj Squares //非常没素质的一道讨论题,不想写。 /*POJ 2826An Easy Problem?!*/ /* 重点不在easy problem,在于后面的两个标点符号。 *哥见的easy problem多了,大都很难,鄙视出题人!这题情况很多,要慢慢讨论: *discuss有一个比较好的: *找出交点P *统计4个点有多少个比p点高,要有两个点a和b才行,比较矮的那个交点a向上的垂直射线是否与高的那点b所在的线是否相交 *不想交就用叉积求面积。 */ #include <cstdio> #include <cstring> #include <cmath> using namespace std; #define max(a,b) ((a)>(b) ? (a) : (b)) #define min(a,b) ((a)<(b) ? (a) : (b)) #define fsm(a,b) ((b) > EPS+(a)) //a < b #define fbgeq(a,b) ((a) >= (b)-EPS) //a >= b #define fsmeq(a,b) ((b) >= (a)-EPS) //a <= b #define EPS 1e-8 #define feq(a,b) (fabs((a)-(b))<EPS) #define fbg(a,b) ((a) > EPS+(b)) struct Point{ double x,y; Point(){} Point(double _x,double _y):x(_x),y(_y){} void input(){ scanf("%lf%lf",&x,&y); } }; struct Segment{ Point a,b; Segment(){} Segment(Point _a,Point _b):a(_a),b(_b){} }; struct Line{ double a,b,c; Line(){} Line(double _a,double _b,double _c):a(_a),b(_b),c(_c){} }; inline double difcross(Point a,Point b,Point c){ return (b.x-a.x)*(c.y-a.y)-(c.x-a.x)*(b.y-a.y); } inline void getline(Point p1,Point p2,Line &l){ l.a = p2.y - p1.y; l.b = p1.x - p2.x; l.c = p1.y*p2.x - p1.x*p2.y; if (l.a < 0) l.a *= -1,l.b *= -1,l.c *= -1; } inline bool line_intersect(Line l1,Line l2,Point &p) { double d=l1.a*l2.b-l2.a*l1.b; if (feq(d, 0)) return 0; p.x = (l2.c*l1.b-l1.c*l2.b)/d; p.y = (l2.a*l1.c-l1.a*l2.c)/d; return true; } inline bool SegIntersect(Segment s1,Segment s2) { if (fabs(difcross(s1.a, s2.a, s2.b)) < EPS && fabs(difcross(s1.b, s2.a, s2.b)) < EPS) return 0; double mxs1x = max(s1.a.x,s1.b.x), mns1x = min(s1.a.x,s1.b.x); double mxs2x = max(s2.a.x,s2.b.x), mns2x = min(s2.a.x,s2.b.x); double mxs1y = max(s1.a.y,s1.b.y), mns1y = min(s1.a.y,s1.b.y); double mxs2y = max(s2.a.y,s2.b.y), mns2y = min(s2.a.y,s2.b.y); return fsmeq(difcross(s1.a,s1.b,s2.a)*difcross(s1.a,s1.b,s2.b), 0)&& fsmeq(difcross(s2.a,s2.b,s1.a)*difcross(s2.a,s2.b,s1.b), 0)&& fbgeq(mxs1x, mns2x)&&fbgeq(mxs2x, mns1x) && fbgeq(mxs1y, mns2y)&&fbgeq(mxs2y, mns1y); } inline double trarea(Point a,Point b,Point c){ return fabs(difcross(a,b,c))/2.0; } int main(){ int n; scanf("%d",&n); Point a,b,c,d,cross; while(n --){ double ans; a.input(); b.input(); c.input(); d.input(); double y1 = max(a.y,b.y); double y2 = max(c.y,d.y); Segment s1,s2; if(fbg(y1,y2)){ s1 = Segment(c,d); s2 = Segment(a,b); } else{ s1 = Segment(a,b); s2 = Segment(c,d); } if(!SegIntersect(s1,s2)){ printf("0.00\n"); continue; } Line l1,l2; getline(a,b,l1); getline(c,d,l2); line_intersect(l1,l2,cross); int cnt = 0; if(fbg(a.y,cross.y))cnt ++; if(fbg(b.y,cross.y))cnt ++; if(fbg(c.y,cross.y))cnt ++; if(fbg(d.y,cross.y))cnt ++; if(cnt < 2){ printf("0.00\n"); continue; } Point tmp = fbg(s1.a.y,s1.b.y) ? s1.a : s1.b; Line l3 = Line(0,1,-tmp.y); Point pp; getline(s2.a,s2.b,l2); line_intersect(l2,l3,pp); Segment s3 = Segment(tmp,Point(tmp.x,1e100)); if(SegIntersect(s2,s3)){ printf("0.00\n"); continue; } ans = trarea(tmp,cross,pp); printf("%.2lf\n",ans); } return 0; } /*POJ 1039 Pipe*/ //恶心的枚举,容易错,注意叉乘的性质,精度1e-3或者不要都可以 #include <cstdio> #include <cstring> #include <cmath> using namespace std; #define EPS 1e-6 #define max(a,b) ((a)>(b) ? (a) : (b)) #define min(a,b) ((a)<(b) ? (a) : (b)) #define a2r(a) (((a)*PI)/180.0)//角度到弧度 #define r2a(a) (((a)/PI)*180.0)//弧度到角度 #define feq(a,b) (fabs((a)-(b))<EPS)//a==b #define fbg(a,b) ((a) > EPS+(b)) //a > b #define fsm(a,b) ((b) > EPS+(a)) //a < b #define fsmeq(a,b) ((b) >= (a)-EPS) //a <= b const int MAXN = 30; struct Point{ double x,y; Point(){} Point(double _x,double _y):x(_x),y(_y){} void input(){ scanf("%lf%lf",&x,&y); } }; Point psa[MAXN],psb[MAXN]; struct Segment{ Point a,b; Segment(){} Segment(Point _a,Point _b):a(_a),b(_b){} }; struct Line{ double a,b,c; Line(){} Line(double _a,double _b,double _c):a(_a),b(_b),c(_c){} }; inline double difcross(Point a,Point b,Point c){ return (b.x-a.x)*(c.y-a.y)-(c.x-a.x)*(b.y-a.y); } inline int SegLineIntersect(Point s1,Point s2,Point e1,Point e2){ if(difcross(e1,e2,s1)*difcross(e1,e2,s2) <= 0)return 1; return 0; } inline void getline(Point p1,Point p2,Line &l){ l.a = p2.y - p1.y; l.b = p1.x - p2.x; l.c = p1.y*p2.x - p1.x*p2.y; if (l.a < 0) l.a *= -1,l.b *= -1,l.c *= -1; } inline bool line_intersect(Line l1,Line l2,Point &p) { double d=l1.a*l2.b-l2.a*l1.b; if (feq(d, 0)) return 0; p.x = (l2.c*l1.b-l1.c*l2.b)/d; p.y = (l2.a*l1.c-l1.a*l2.c)/d; return true; } int n; int main(){ while(scanf("%d",&n) != EOF){ if(n == 0)break; double ans = -1e100; for(int i = 0; i < n; ++i){ psa[i].input(); psb[i] = Point(psa[i].x,psa[i].y-1); } Line l1,l2,l3,l; Point cross; Segment s1,s2; for(int i = 0; i < n; ++i){ for(int j = 0; j < n; ++j){ if(i == j)continue; int k = max(i,j); int tag; getline(psa[i],psb[j],l); for(tag = 0; tag < n; tag++){ if(fsmeq(difcross(psa[i],psa[tag],psb[j])* difcross(psa[i],psb[tag],psb[j]),0)) continue; else break; } if(tag < k)continue; if(tag == n){ ans = psa[n-1].x; break; } if(SegLineIntersect(psa[tag-1],psa[tag],psa[i],psb[j])){ getline(psa[tag-1],psa[tag],l1); line_intersect(l1,l,cross); if(ans < cross.x)ans = cross.x; } if(SegLineIntersect(psb[tag-1],psb[tag],psa[i],psb[j])){ getline(psb[tag-1],psb[tag],l1); line_intersect(l1,l,cross); if(ans < cross.x)ans = cross.x; } } } if(ans == psa[n-1].x)puts("Through all the pipe."); else printf("%.2lf\n",ans); } return 0; } /*POJ 3449 Geometric Shapes*/ //堪称屎上第一屎的题目,输入输出都很烦,判断几何体是否相交 ///没见过输入输出这么没素质的,光输入输出处理了100多行,没办法,谁让咱不是出题的。 //其实就利用了一个线段相交判断,还有一个就是已知正方形的对角线上两个点,求出另外两个点的坐标 #include <cstdio> #include <cstring> #include <cmath> #include <algorithm> using namespace std; #define EPS 1e-16 #define max(a,b) ((a)>(b) ? (a) : (b)) #define min(a,b) ((a)<(b) ? (a) : (b)) #define feq(a,b) (fabs((a)-(b))<EPS)//a==b #define fbg(a,b) ((a) > EPS+(b)) //a > b #define fsm(a,b) ((b) > EPS+(a)) //a < b #define fbgeq(a,b) ((a) >= (b)-EPS) //a >= b #define fsmeq(a,b) ((b) >= (a)-EPS) //a <= b const int MAXN = 30; struct Point{ double x,y; Point(){} Point(double _x,double _y):x(_x),y(_y){} void input(){ scanf("%lf%lf",&x,&y); } }; struct Segment{ Point a,b; Segment(){} Segment(Point _a,Point _b):a(_a),b(_b){} }; struct Thing{ char tag; Point p[25]; char op[20]; int n; inline int input(){ scanf(" %c",&tag); if(tag == '.')return -1; if(tag == '-')return 0; scanf(" %s",op); if(!strcmp(op,"square")){ n = 4; scanf(" (%lf,%lf)",&p[1].x,&p[1].y); scanf(" (%lf,%lf)",&p[3].x,&p[3].y); Point b, d; double x,y,mx, my; mx = (p[1].x+p[3].x)/2.0, my = (p[1].y+p[3].y)/2.0; x = p[1].x - mx; y = p[1].y - my; p[2].x = -y + mx; p[2].y = x + my; p[4] = Point(p[1].x+p[3].x-p[2].x,p[1].y+p[3].y-p[2].y); p[0] = p[4]; } else if(!strcmp(op,"triangle")){ n = 3; scanf(" (%lf,%lf)",&p[1].x,&p[1].y); scanf(" (%lf,%lf)",&p[2].x,&p[2].y); scanf(" (%lf,%lf)",&p[3].x,&p[3].y); p[0] = p[3]; } else if(!strcmp(op,"line")) { n = 2; scanf(" (%lf,%lf)",&p[1].x,&p[1].y); scanf(" (%lf,%lf)",&p[2].x,&p[2].y); p[0] = p[2]; } else if(!strcmp(op,"rectangle")){ n = 4; scanf(" (%lf,%lf)",&p[1].x,&p[1].y); scanf(" (%lf,%lf)",&p[2].x,&p[2].y); scanf(" (%lf,%lf)",&p[3].x,&p[3].y); p[4] = Point(p[1].x+p[3].x-p[2].x,p[1].y+p[3].y-p[2].y); p[0] = p[4]; } else if(!strcmp(op,"polygon")){ scanf("%d",&n); for(int i = 1; i <= n; ++i) scanf(" (%lf,%lf)",&p[i].x,&p[i].y); p[0] = p[n]; } return 1; } }; inline double difcross(Point a,Point b,Point c){ return (b.x-a.x)*(c.y-a.y)-(c.x-a.x)*(b.y-a.y); } inline bool SegIntersect(Segment s1,Segment s2) { double mxs1x = max(s1.a.x,s1.b.x), mns1x = min(s1.a.x,s1.b.x); double mxs2x = max(s2.a.x,s2.b.x), mns2x = min(s2.a.x,s2.b.x); double mxs1y = max(s1.a.y,s1.b.y), mns1y = min(s1.a.y,s1.b.y); double mxs2y = max(s2.a.y,s2.b.y), mns2y = min(s2.a.y,s2.b.y); return fsmeq(difcross(s1.a,s1.b,s2.a)*difcross(s1.a,s1.b,s2.b), 0)&& fsmeq(difcross(s2.a,s2.b,s1.a)*difcross(s2.a,s2.b,s1.b), 0)&& fbgeq(mxs1x, mns2x)&&fbgeq(mxs2x, mns1x) && fbgeq(mxs1y, mns2y)&&fbgeq(mxs2y, mns1y); } inline bool Intersect(Thing a,Thing b){ int flag = 0; Segment s1,s2; for(int i = 0; i < a.n; ++i){ for(int j = 0; j < b.n; ++j){ s1 = Segment(a.p[i],a.p[i+1]); s2 = Segment(b.p[j],b.p[j+1]); if(SegIntersect(s1,s2))return 1; } } return 0; } inline int cmp(Thing a,Thing b){ return a.tag < b.tag; } Thing things[MAXN]; char ans[MAXN]; int main(){ int top; Thing tmp; while(tmp.input() != -1){ if(tmp.tag == '-')continue; top = 0; things[top] = tmp; while(tmp.input() != 0){ things[++top] = tmp; } top ++; sort(things,things+top,cmp); for(int i = 0; i < top; ++i){ int t = 0; printf("%c ",things[i].tag); for(int j = 0; j < top; ++j){ if(i == j)continue; if(Intersect(things[i],things[j])){ ans[t++] = things[j].tag; } } if(t == 0) puts("has no intersections"); else if(t == 1) printf("intersects with %c\n",ans[0]); else if(t == 2) printf("intersects with %c and %c\n",ans[0],ans[1]); else{ printf("intersects with "); for(int j = 0; j < t - 1; ++j) printf("%c, ",ans[j]); printf("and %c\n",ans[t-1]); } } puts(""); } return 0; } /*POJ 1584 A Round Peg in a Ground Hole*/ //这题用的东西很多,包括点到直线距离,圆与多边形相交(圆在多边形内判断),判断多边形是否为凸多边形 /* 关于圆在多边形内判断,要先判断圆心是否在多边形内,这个我是套的点在多边形内的模板,对于凸多边形,有一种特定的方法去判断(这样的话代码长度会大大缩短):点在已知凸包内(包括三点共线)====》其对于所有边的叉乘同大于等于0或小于等于0;本人代码仅供个人观赏。一般人看不懂。 */ #include <cstdio> #include <cstring> #include <cmath> #include <algorithm> using namespace std; #define INF 1e100 #define EPS 1e-8 #define PI acos(-1.0) #define max(a,b) ((a)>(b) ? (a) : (b)) #define min(a,b) ((a)<(b) ? (a) : (b)) #define feq(a,b) (fabs((a)-(b))<EPS)//a==b #define fbg(a,b) ((a) > EPS+(b)) //a > b #define fsm(a,b) ((b) > EPS+(a)) //a < b #define fbgeq(a,b) ((a) >= (b)-EPS) //a >= b #define fsmeq(a,b) ((b) >= (a)-EPS) //a <= b const int MAXN = 100010; struct Point{ double x,y; Point(){} Point(double _x,double _y):x(_x),y(_y){} void input(){ scanf("%lf%lf",&x,&y); } }; struct Segment{ Point a,b; Segment(){} Segment(Point _a,Point _b):a(_a),b(_b){} }; struct Circle{ Point cer; double radious; Circle(){} Circle(Point _cer,double _radious):cer(_cer),radious(_radious){} void input(){ scanf("%lf",&radious); cer.input(); } }; struct Line{ double a,b,c; Line(){} Line(double _a,double _b,double _c):a(_a),b(_b),c(_c){} }; inline double pdis(Point a,Point b){ return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y)); } inline double difcross(Point a,Point b,Point c){ return (b.x-a.x)*(c.y-a.y)-(c.x-a.x)*(b.y-a.y); } inline double p2seg(Point a,Point p1,Point p2){ return fabs(difcross(a,p1,p2))/pdis(p1,p2); } inline bool SegIntersect(Segment s1,Segment s2) { if (fabs(difcross(s1.a, s2.a, s2.b)) < EPS && fabs(difcross(s1.b, s2.a, s2.b)) < EPS) return 0; double mxs1x = max(s1.a.x,s1.b.x), mns1x = min(s1.a.x,s1.b.x); double mxs2x = max(s2.a.x,s2.b.x), mns2x = min(s2.a.x,s2.b.x); double mxs1y = max(s1.a.y,s1.b.y), mns1y = min(s1.a.y,s1.b.y); double mxs2y = max(s2.a.y,s2.b.y), mns2y = min(s2.a.y,s2.b.y); return fsmeq(difcross(s1.a,s1.b,s2.a)*difcross(s1.a,s1.b,s2.b), 0)&& fsmeq(difcross(s2.a,s2.b,s1.a)*difcross(s2.a,s2.b,s1.b), 0)&& fbgeq(mxs1x, mns2x)&&fbgeq(mxs2x, mns1x) && fbgeq(mxs1y, mns2y)&&fbgeq(mxs2y, mns1y); } inline int PonSeg(Point a,Point p1,Point p2){ if(fabs(difcross(a,p1,p2)) <= EPS && a.x >= min(p1.x,p2.x) && a.x <= max(p1.x,p2.x) && a.y >= min(p1.y,p2.y) && a.y <= max(p1.y,p2.y)) return 1; return 0; } #define on_s2r(p, s) (feq(p.y, s.y) && fbgeq(p.x, s.x)) inline int p_in_polygon(Point a,Point p[],int np) { //点a是否在点数为np的多边形内 int count = 0; Segment s,ps; ps.a = a,ps.b = a; ps.b.x = INF; for(int i = 0;i < np;i++){ s.a = p[i]; if(i + 1 < np)s.b = p[i+1]; else s.b = p[0]; if (s.a.y > s.b.y)swap(s.a,s.b); if (PonSeg(a,s.a,s.b))return 2; if (!feq(s.a.y, s.b.y)){ if (on_s2r(s.b, a)) count++; else if (!on_s2r(s.a, a) && SegIntersect(s,ps))count++; } } if (count%2)return 1; return 0; } /*对于凸多边形,还可以这样判断(代替普通的射线法求点在多边形内): inline int p_in_polygon(Point a,Point p[],int np) { p[np] = p[0]; p[np+1] = p[1]; for(int i = 0; i < np; ++i){ double tmp = difcross(a,p[i],p[i+1])*difcross(a,p[i+1],p[i+2]); if(tmp < -EPS)return 0; } return 1; } */ inline bool cir_in_polygon(Circle a,Point ps[],int np){ int ans = p_in_polygon(a.cer,ps,np); if(ans == 0)return 0; double mi = INF; ps[np] = ps[0]; for(int i = 0; i < np; ++i){ double t = p2seg(a.cer,ps[i],ps[i+1]); mi = min(mi,t); } if(fbgeq(mi,a.radious))return 1; return 0; } inline bool isTu(Point ps[],int n){ ps[n] = ps[0]; for(int i = 0; i < n; ++i){ for(int j = 0; j < n; ++j){ double tmp = difcross(ps[i],ps[i+1],ps[j])*difcross(ps[i],ps[i+1],ps[j+1]); if(tmp < -EPS)return 0; } } return 1; } int main(){ Circle a; Point ps[MAXN]; int n; while(scanf("%d",&n) != EOF){ if(n < 3)break; a.input(); for(int i = 0; i < n; ++i)ps[i].input(); if(!isTu(ps,n)){ puts("HOLE IS ILL-FORMED"); continue; } if(cir_in_polygon(a,ps,n)){ puts("PEG WILL FIT"); continue; } puts("PEG WILL NOT FIT"); } return 0; } /*POJ 2074 Line of Sight*/ //鄙视好多trick的题,特别是有trick的计算几何题,障碍物可能在房子以上或者线以下,然后注意直线和线段不相交的时候的情况 //有好几种 ,我的代码很长,应该是方法不好,因为我先求的是被覆盖的区间然后处理的 #include <cstdio> #include <cstring> #include <cmath> #include <algorithm> using namespace std; #define EPS 1e-8 #define max(a,b) ( (a) > (b) ? (a) : (b) ) #define min(a,b) ( (a) < (b) ? (a) : (b) ) #define feq(a,b) (fabs((a)-(b))<EPS)//a==b #define fbg(a,b) ((a) > EPS+(b)) //a > b #define fsm(a,b) ((b) > EPS+(a)) //a < b #define fbgeq(a,b) ((a) >= (b)-EPS) //a >= b #define fsmeq(a,b) ((b) >= (a)-EPS) //a <= b const int MAXN = 1000; struct Point{ double x,y; Point(){} Point(double _x,double _y):x(_x),y(_y){} void input(){ scanf("%lf%lf",&x,&y); } }; struct Line{ double a,b,c; Line(){} Line(double _a,double _b,double _c):a(_a),b(_b),c(_c){} }; Line tmp,line; inline double difcross(Point a,Point b,Point c){ return (b.x-a.x)*(c.y-a.y)-(c.x-a.x)*(b.y-a.y); } inline void getline(Point p1,Point p2,Line &l){ l.a = p2.y - p1.y; l.b = p1.x - p2.x; l.c = p1.y*p2.x - p1.x*p2.y; if (l.a < 0) l.a *= -1,l.b *= -1,l.c *= -1; } inline bool line_intersect(Line l1,Line l2,Point &p) { double d=l1.a*l2.b-l2.a*l1.b; if (feq(d, 0)) return 0; p.x = (l2.c*l1.b-l1.c*l2.b)/d; p.y = (l2.a*l1.c-l1.a*l2.c)/d; return true; } struct Ans{ double x1,x2; }; Ans ans[MAXN]; inline int cmp(Ans a,Ans b){ return a.x1 < b.x1; } int main(){ double a,b,c; Point ha,hb; Point la,lb; while(scanf("%lf%lf%lf",&a,&b,&c) != EOF){ if(a == 0 && b == 0 && c == 0)break; ha = Point(a,c); hb = Point(b,c); scanf("%lf%lf%lf",&a,&b,&c); la = Point(a,c); lb = Point(b,c); getline(la,lb,line); int n; Point ta,tb,tt; scanf("%d",&n); bool flag = 0; for(int i = 0; i < n; ++i){//直接求的直线与直线相交 scanf("%lf%lf%lf",&a,&b,&c); if(fsmeq(ha.y,c)||fsmeq(c,la.y)){ ans[i].x1 = ans[i].x2 = lb.x; continue; } ta = Point(a,c); tb = Point(b,c); getline(ha,tb,tmp); line_intersect(tmp,line,tt); ans[i].x2 = tt.x; getline(hb,ta,tmp); line_intersect(tmp,line,tt); ans[i].x1 = tt.x; } sort(ans,ans+n,cmp); double cur = la.x; double res = 0; int t = 0; while(t < n){ if(fsm(res,ans[t].x1-cur)) res = ans[t].x1-cur; cur = max(cur,ans[t].x2); t ++; } if(fsm(res,lb.x-cur))res = lb.x-cur; if(feq(res,0))printf("No View\n"); else printf("%.2lf\n",res); } } 二、凸包问题 /*POJ 1113 Wall*/ //裸的凸包,可以做模板 #include <cstdio> #include <cstring> #include <cmath> #include <algorithm> using namespace std; #define max(a,b) ((a) > (b) ? (a) : (b)) #define min(a,b) ((a) < (b) ? (a) : (b)) #define EPS 1e-8 #define PI acos(-1.0) #define feq(a,b) (fabs((a)-(b))<EPS)//a==b #define fbg(a,b) ((a) > EPS+(b)) //a > b #define fsm(a,b) ((b) > EPS+(a)) //a < b #define fbgeq(a,b) ((a) >= (b)-EPS) //a >= b #define fsmeq(a,b) ((b) >= (a)-EPS) //a <= b const int MAXN = 1000; struct Point{ double x,y; Point(){} Point(double _x,double _y):x(_x),y(_y){} void input(){ scanf("%lf%lf",&x,&y); } }; inline double pdis(Point a,Point b){ return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y)); } inline double difcross(Point a,Point b,Point c){ return (b.x-a.x)*(c.y-a.y)-(c.x-a.x)*(b.y-a.y); } Point p0; int top,n,graham[MAXN]; Point points[MAXN]; inline int cmp(Point a, Point b) { double k = difcross(p0, a, b); if(feq(k,0) && fbg(pdis(a, p0) , pdis(b, p0)))return 1; else if( k > EPS ) return 1; return 0; } inline void Graham(){ int i,u = 0; for(i = 1; i < n; i++){ if(fsm(points[i].y , points[u].y)||feq(points[i].y , points[u].y) &&fsm(points[i].x , points[u].x) )u = i; } swap(points[0],points[u]); p0 = points[0]; sort( points+1, points + n, cmp ); graham[0] = 0; graham[1] = 1; graham[2] = 2; top = 2; for( i = 3; i < n; i++){ while(difcross(points[i],points[graham[top]],points[graham[top-1]]) > EPS){ top--; if(top == 0)break; } graham[++top] = i; } } double ans,R; inline void solve(){ Graham(); ans = 0; for(int i = 0; i < top; ++i){ ans += pdis(points[graham[i]],points[graham[i+1]]); } ans += pdis(points[graham[0]],points[graham[top]]); ans += 2.0*PI*R; printf("%.0lf\n",ans); } int main(){ scanf("%d%lf",&n,&R); for(int i = 0; i < n; ++i) points[i].input(); solve(); } /*POJ 2007 Scrambled Polygon */ //求凸包的过程中极角排序这个思想的应用,非常重要,注意sort中的cmp怎么写的 #include <cstdio> #include <cstring> #include <cmath> #include <algorithm> using namespace std; #define max(a,b) ((a) > (b) ? (a) : (b)) #define min(a,b) ((a) < (b) ? (a) : (b)) #define EPS 1e-8 #define PI acos(-1.0) #define feq(a,b) (fabs((a)-(b))<EPS)//a==b #define fbg(a,b) ((a) > EPS+(b)) //a > b #define fsm(a,b) ((b) > EPS+(a)) //a < b #define fbgeq(a,b) ((a) >= (b)-EPS) //a >= b #define fsmeq(a,b) ((b) >= (a)-EPS) //a <= b const int MAXN = 55; struct Point{ double x,y; Point(){} Point(double _x,double _y):x(_x),y(_y){} void input(){ scanf("%lf%lf",&x,&y); } }; inline double pdis(Point a,Point b){ return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y)); } inline double difcross(Point a,Point b,Point c){ return (b.x-a.x)*(c.y-a.y)-(c.x-a.x)*(b.y-a.y); } Point p0; int n; Point points[MAXN]; inline int cmp(Point a, Point b) { double k = difcross(p0, a, b); if(feq(k,0) && fbg(pdis(a, p0) , pdis(b, p0)))return 1; else if( k > EPS ) return 1; return 0; } int main(){ int top = 0; double x0,y0; while(scanf("%lf%lf",&x0,&y0) != EOF){ //if(x0 == -1 && y0 == -1)break; points[top++] = Point(x0,y0); } p0 = points[0]; sort(points+1,points+1+top,cmp); for(int i = 0; i < top; ++i) printf("(%.0lf,%.0lf)\n",points[i].x,points[i].y); return 0; } /*POJ 1873 The Fortified Forest*/ //1999年worldfinal的题,纯暴力可以过,用位运算的枚举,枚举出2^n种状态,取最优解法即可。 #include <cstdio> #include <cstring> #include <cmath> #include <algorithm> using namespace std; #define EPS 1e-6 #define max(a,b) ((a)>(b) ? (a) : (b)) #define min(a,b) ((a)<(b) ? (a) : (b)) #define feq(a,b) (fabs((a)-(b))<EPS)//a==b #define fbg(a,b) ((a) > EPS+(b)) //a > b #define fsm(a,b) ((b) > EPS+(a)) //a < b #define fbgeq(a,b) ((a) >= (b)-EPS) //a >= b #define fsmeq(a,b) ((b) >= (a)-EPS) //a <= b const int MAXN = 20; double len[MAXN]; double val[MAXN]; struct Point{ double x,y; Point(){} Point(double _x,double _y):x(_x),y(_y){} void input(){ scanf("%lf%lf",&x,&y); } }; inline double difcross(Point a,Point b,Point c){ return (b.x-a.x)*(c.y-a.y)-(c.x-a.x)*(b.y-a.y); } inline double pdis(Point a,Point b){ return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y)); } int graham[MAXN],top; Point p0; Point p[MAXN],points[MAXN]; inline int cmp(Point a, Point b) { double k = difcross(p0, a, b); if(feq(k,0) && fbg(pdis(a, p0) , pdis(b, p0)))return 1; else if( k > EPS ) return 1; return 0; } inline void Graham(Point points[],int n){ if(n < 3){ if(n == 0 || n == 1)top = 0; if(n == 2)top = 1; return; } int i,u = 0; for(i = 1; i < n; i++){ if(fsm(points[i].y , points[u].y)||feq(points[i].y , points[u].y) &&fsm(points[i].x , points[u].x) )u = i; } swap(points[0],points[u]); p0 = points[0]; sort( points+1, points + n, cmp ); graham[0] = 0; graham[1] = 1; graham[2] = 2; top = 2; for( i = 3; i < n; i++){ while(difcross(points[i],points[graham[top]],points[graham[top-1]])> EPS){ top--; if(top == 0)break; } graham[++top] = i; } } inline double girth(){ double ans = 0; for(int i = 0; i < top ; ++i){ ans += pdis(points[graham[i]],points[graham[i+1]]); } ans += pdis(points[graham[top]],points[graham[0]]); return ans; } int main(){ int n; int cas = 0; while(scanf("%d",&n) != EOF){ if(n == 0)break; cas ++; if(cas != 1)puts(""); for(int i = 0; i < n; ++i){ p[i].input(); scanf("%lf",&val[i]); scanf("%lf",&len[i]); } int tn = 1<<n; double ans = 1e100,tans; int res = 0; for(int tag = 0; tag < tn; tag ++){ int tt = 0;double tlen = 0,tval = 0; for(int j = 0; j < n; ++j){ int t = 1<<j; if(t&tag) points[tt++] = p[j]; else { tlen += len[j]; tval += val[j]; } } Graham(points,tt); double need_len = girth(); if(fbgeq(tlen,need_len) && fbg(ans,tval)){ ans = tval; res = tag; tans = tlen - need_len; } } printf("Forest %d\n",cas); printf("Cut these trees:"); for(int j = 0; j < n; ++j){ if((1<<j)&res)continue; printf(" %d",j+1); } puts(""); printf("Extra wood: %.2lf\n",tans); } return 0; } /*POJ 1228 Grandpa's Estate*/ //题意比较难理解,给n个凸多边形上的点,问能不能唯一确定这个凸多边形。 //刚写凸包的时候写的这个题,代码风格和现在很不一样 /* 这是这题的做法,黑书上的题 1. n<=5,一律输出NO 2. 所有点共线,NO 3. 凸包上每条边上至少有三点,否则NO */ #include<iostream> #include<stdio.h> #include<string.h> #include<algorithm> using namespace std; #define eps 1e-8 #define MAXN 1005 #define zero(x) (((x)>0?(x):-(x))<eps) struct point { double x,y; }; point P[MAXN],convex[MAXN]; int t,n,i,j,flag[MAXN],k; double xmult(point p1,point p2,point p0){ return (p1.x-p0.x)*(p2.y-p0.y)-(p2.x-p0.x)*(p1.y-p0.y); } point p1,p2; int graham_cp(const void* a,const void* b){ double ret=xmult(*((point*)a),*((point*)b),p1); return zero(ret)?(xmult(*((point*)a),*((point*)b),p2)>0?1:-1):(ret>0?1:-1); } void _graham(int n,point* p,int& s,point* ch){ int i,k=0; for (p1=p2=p[0],i=1;i<n;p2.x+=p[i].x,p2.y+=p[i].y,i++) if (p1.y-p[i].y>eps||(zero(p1.y-p[i].y)&&p1.x>p[i].x)) p1=p[k=i]; p2.x/=n,p2.y/=n; p[k]=p[0],p[0]=p1; qsort(p+1,n-1,sizeof(point),graham_cp); for (ch[0]=p[0],ch[1]=p[1],ch[2]=p[2],s=i=3;i<n;ch[s++]=p[i++]) for (;s>2&&xmult(ch[s-2],p[i],ch[s-1])<-eps;s--); } int graham(int n,point* p,point* convex,int maxsize=0,int dir=1){ point* temp=new point[n]; int s,i; _graham(n,p,s,temp); for (convex[0]=temp[0],n=1,i=(dir?1:(s-1));dir?(i<s):i;i+=(dir?1:-1)) if (maxsize||!zero(xmult(temp[i-1],temp[i],temp[(i+1)%s]))) convex[n++]=temp[i]; delete []temp; return n; } int dot_online_in(point p,point l1,point l2) { return zero(xmult(p,l1,l2))&&(l1.x-p.x)*(l2.x-p.x)<eps&&(l1.y-p.y)*(l2.y-p.y)<eps; } int main() { scanf("%d",&t); while(t--) { scanf("%d",&n); for(i=0;i<n;i++) { scanf("%lf %lf",&P[i].x,&P[i].y); } if(n<=5) { printf("NO\n"); continue; } k=0; for(i=1;i<n-1;i++) { if(xmult(P[0],P[n-1],P[i])!=0) { k=1; break; } } if(!k) { printf("NO\n"); continue; } int M=graham(n,P,convex,0,1); if(M==n) { printf("NO\n"); continue; } memset(flag,0,sizeof(flag)); for(i=0;i<n;i++) { for(j=0;j<M-1;j++) { if(dot_online_in(P[i],convex[j],convex[j+1])) { flag[j]++; } } if(dot_online_in(P[i],convex[M-1],convex[0])) { flag[M-1]++; } } k=0; for(i=0;i<M;i++){ if(flag[i]<3){ k=1; break; } } if(!k) printf("YES\n"); else printf("NO\n"); } return 0; } /*POJ 3348 Cows */ //求凸包面积 #include<iostream> #include<string.h> #include<stdio.h> #include<string.h> #include<cmath> #include<algorithm> using namespace std; const int maxn = 10010; struct Point { double x; double y; }; Point p[maxn]; int n; double pdis(Point a,Point b){ return sqrt((a.x - b.x)*(a.x - b.x)+(a.y - b.y)*(a.y - b.y)); } double det(Point p0,Point p1,Point p2){ return (p1.x-p0.x)*(p2.y-p0.y)-(p2.x-p0.x)*(p1.y - p0.y); } int cmp(Point a,Point b){ double k = det(p[0],a,b); if(k > 0)return 1; else if(k == 0 && pdis(p[0],a) - pdis(p[0],b) > 0)return 1; return 0; } int graham[maxn]; int top; void Graham(){ int i,u = 0; for(i = 1; i < n; i++){ if(p[i].y < p[u].y || (p[i].y == p[u].y && p[i].x < p[u].x))u = i; } Point t; t.x = p[u].x;t.y = p[u].y; p[u] = p[0]; p[0] = t; sort(p+1,p+n,cmp); graham[0] = 0; graham[1] = 1; graham[2] = 2; top = 2; for(i = 3; i < n; i++){ while(det(p[i],p[graham[top]],p[graham[top-1]]) > 0){ top--; if(top == 0)break; } graham[++top] = i; } } int main(){ scanf("%d",&n); for(int i = 0; i < n; i++){ scanf("%lf%lf",&p[i].x,&p[i].y); } double area = 0; Graham(); Point t; t.x = 0.000;t.y = 0.000; for(int i = 0; i < top; i++){ area += det(t,p[graham[i]],p[graham[i+1]]); } area += det(t,p[graham[top]],p[graham[0]]); area = fabs(area)/2; area /= 50; int ans = int(area); printf("%d\n",ans); return 0; } 三、面积问题,公式问题 /*POJ 1654 Area */ //多边形面积计算,利用叉积,水题 #include <cstdio> #include <cstring> using namespace std; struct p{ int x,y; }; int square(p a,p b,p c){ int r = (b.x-a.x)*(c.y-b.y)-(b.y-a.y)*(c.x-b.x); return r; } int main() { int n; int move[10][2]={{0,0},{-1,-1},{0,-1},{1,-1},{-1,0},{0,0},{1,0},{-1,1},{0,1},{1,1} }; scanf("%d",&n); char ch[1000100]; while(n--) { scanf("%s",ch); int len = strlen(ch); int i,j,k; p a,b,c; a.x=0,a.y=0; c.x=a.x+move[ch[0]-'0'][0]; c.y=a.y+move[ch[0]-'0'][1]; __int64 s =0; for(i=1;i<len;i++) { b=c; c.x=b.x+move[ch[i]-'0'][0]; c.y=b.y+move[ch[i]-'0'][1]; s+=square(a,b,c); } if(s<0)s=-s; printf("%I64d",s/2); if(s%2) printf(".5"); printf("\n"); } return 0; } /*POJ 1265 Area */ /*利用Pick定理,Pick定理是说,假设平面上有一个顶点全在格点上的多边形P,那么其面积S(P)应该等于i+b/2-1,其中i为多边形内部所含的格点数,b是多边形边界上的格点数。关于pick定理的证明,这里有一个http://www.matrix67.com/blog/archives/768*/ //求边上有多少个格点的时候用最大公约数 #include<cstring> #include<cmath> #include<cstdio> using namespace std; struct point{double x,y;}; int gcd(int a,int b){ if(b == 0)return a; else return gcd(b,a%b); } double area_polygon(int n,point* p){ double s1=0,s2=0; int i; for (i=0;i<n;i++) s1+=p[(i+1)%n].y*p[i].x,s2+=p[(i+1)%n].y*p[(i+2)%n].x; return fabs(s1-s2)/2; } point p[103]; int main() { int testcase; int n; int i,j; double I,E,s; int x,y; scanf("%d",&testcase); for(i=1;i<=testcase;i++) { E=0; scanf("%d",&n); point temp; temp.x=temp.y=0; p[0]=temp; double dx,dy; for(j=1;j<=n;j++) { scanf("%lf%lf",&dx,&dy); temp.x+=dx; temp.y+=dy; p[j]=temp; } s=area_polygon(n,p); for(j=1;j<n;j++) E+=gcd((int)(abs(p[j].x-p[j-1].x)+0.1),(int)(abs(p[j].y-p[j-1].y)+0.1)); E+=gcd((int)(abs(p[n-1].x-p[0].x)+0.1),(int)(abs(p[n-1].y-p[0].y)+0.1)); I=s+1-E/2; printf("Scenario #%d:\n",i); printf("%.0lf %.0lf %.1lf\n\n",I,E,s); } return 0; } /*POJ 2954 Triangle*/ //Pick定理的应用 #include <cstdio> #include <cstring> #include <cmath> using namespace std; struct Point{ double x,y; void input(){ scanf("%lf%lf",&x,&y); } }; Point a,b,c; inline int Input(){ a.input(); b.input(); c.input(); if(a.x == 0 && b.x == 0 && c.x == 0 && a.y == 0 && b.y == 0 && c.y == 0)return 0; return 1; } inline double difcross(Point a,Point b,Point c){ return (b.x-a.x)*(c.y-a.y)-(c.x-a.x)*(b.y-a.y); } inline double trarea(Point a,Point b,Point c){ return fabs(difcross(a,b,c))/2.0; } inline int gcd(int a,int b){ if(b == 0)return a; else return gcd(b,a%b); } int main(){ while(Input()){ double area = trarea(a,b,c); double E = 0; E += gcd((int)fabs(a.x-b.x),(int)fabs(a.y-b.y)); E += gcd((int)fabs(b.x-c.x),(int)fabs(b.y-c.y)); E += gcd((int)fabs(c.x-a.x),(int)fabs(c.y-a.y)); double ans = area+1-E/2; printf("%.0lf\n",ans); } return 0; } 四、半平面交 关于半平面交,见下下一篇文章《半平面交》文章里关于半平面交的所有的题目都有 五、计算几何背景,实际上解题的关键是其他问题(数据结构、组合数学,或者是 枚举思想) 若干道经典的离散化+扫描线的题目,ACM选手必做题目 这一部分比较难,涉及到各种数据结构,各种思想,主要不在计算几何,先空着。 /*POJ 2002 Squares*/ //给若干个点,问能组成多少个正方形,hash可以解决 #include <cstdio> #include <cstring> #include<cmath> #include<vector> #include<algorithm> using namespace std; struct seg{ int x,y; }; seg points[2010]; vector < seg > hash[40010]; int find(int x1,int y1){ int t = abs((x1+y1)/2); int flag = 0; for(int i = 0; i < hash[t].size(); i++){ seg tq = hash[t][i]; if(tq.x == x1 && tq.y == y1){ flag = 1; break; } } return flag; } int main(){ int n,i,j; while(scanf("%d",&n)!=EOF){ if(n == 0)break; int cnt = 0; int x,y; for(i = 0; i <= 40000; i++)hash[i].clear(); for(i = 0; i < n; i++){ scanf("%d%d",&x,&y); points[i].x = x;points[i].y = y; int mid = abs((x+y)/2); if(!find(x,y))hash[mid].push_back(points[i]); } int a1,b1,a2,b2,x1,y1,x2,y2; for(i = 0; i < n; i++){ for(j = i+1; j < n; j++){ a1 = points[i].x; a2 = points[i].y; b1 = points[j].x; b2 = points[j].y; x1 = a1 + b2 - a2; y1 = a2 - b1 + a1; x2 = b1 + b2 - a2; y2 = b2 - b1 + a1; if(find(x1,y1) && find(x2,y2))cnt++; x1 = a1 - b2 + a2; y1 = a2 + b1 - a1; x2 = b1 - b2 + a2; y2 = b2 + b1 - a1; if(find(x1,y1) && find(x2,y2))cnt++; } } printf("%d\n",cnt/4); } return 0; } 六、随机算法 /*POJ 2420 A Star not a Tree?*/ /*第一次做关于随机算法的题目,求多边形的费马点,所谓费马点,就是多边形中的一个点,该点到其他点的距离之和最短,好像只有三角形可以有公式去求费马点,而四边形以上的多边形就要用其他方法了,这个方法就是随机化变步长贪心法、就是选取初始点,然后上下左右向四个方向移动这个点,一直选取最优解,直到上下左右四个方向都不如该点时就OK,然后改变步长继续判断*/ #include <cstdio> #include <cstring> #include <cmath> using namespace std; const int MAXN = 1000; struct Point{ double x,y; Point(){} Point(double _x,double _y):x(_x),y(_y){} void input(){ scanf("%lf%lf",&x,&y); } }; Point points[MAXN],tmp; int n; double di[4][2] = {{0,1.0},{0,-1.0},{1.0,0},{-1.0,0}}; inline double pdis(Point a,Point b){ return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y)); } inline double cal(Point a){ double res = 0; for(int i = 0; i < n; ++i){ res += pdis(points[i],a); } return res; } int main(){ while(scanf("%d",&n) != EOF){ for(int i = 0; i < n; ++i)points[i].input(); Point tt; tmp = points[0]; double ans = cal(tmp); double step = 1000; bool flag = 1; while(step > 0.2){ flag = 1; while(flag){ flag = 0; for(int i = 0; i < 4; ++i){ tt = Point(tmp.x+di[i][0]*step,tmp.y+di[i][1]*step); double caltt = cal(tt); if(caltt < ans){ ans = caltt; tmp = tt; flag = 1; } } } step /= 2; } printf("%.0lf\n",ans); } return 0; } 七、解析几何 /*POJ 1375 Intervals */ //求圆的切线的一道题,求圆的切点的时候用向量旋转即可 #include <cstdio> #include <cstring> #include <cmath> #include <algorithm> using namespace std; #define EPS 1e-8 #define max(a,b) ((a)>(b) ? (a) : (b)) #define min(a,b) ((a)<(b) ? (a) : (b)) #define feq(a,b) (fabs((a)-(b))<EPS)//a==b #define fbg(a,b) ((a) > EPS+(b)) //a > b #define fsm(a,b) ((b) > EPS+(a)) //a < b #define fbgeq(a,b) ((a) >= (b)-EPS) //a >= b #define fsmeq(a,b) ((b) >= (a)-EPS) //a <= b const int MAXN = 1000; struct Point{ double x,y; Point(){} Point(double _x,double _y):x(_x),y(_y){} void input(){ scanf("%lf%lf",&x,&y); } void output(){ printf("%lf %lf\n",x,y); } }; struct Node{ double lx,rx; }; Point light; inline double pdis(Point a,Point b){ return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y)); } inline Point rotate(Point p,double angle){ Point res; res.x=p.x*cos(angle)-p.y*sin(angle); res.y=p.x*sin(angle)+p.y*cos(angle); return res; } inline void GetcutPoint(Point o,double r,Point &res1,Point &res2){ Point t = Point(light.x-o.x,light.y-o.y); double tmp = r/pdis(o,light); double angle = acos(tmp); t.x /= pdis(o,light); t.y /= pdis(o,light); t.x *= r; t.y *= r; res1 = rotate(t,angle); res2 = rotate(t,-angle); res1.x += o.x;res1.y += o.y; res2.x += o.x; res2.y += o.y; } inline void getline(Point x,Point y,double &a,double &b,double &c){ a = y.y - x.y; b = x.x - y.x; c = y.x * x.y - x.x * y.y; } inline int cmp(Node a,Node b){ return a.lx < b.lx; } int main(){ int n; while(scanf("%d",&n) != EOF){ if(n == 0)break; light.input(); double r; Point o; Node nodes[MAXN]; for(int i = 0; i < n; ++i){ o.input(); scanf("%lf",&r); Point res1,res2; GetcutPoint(o,r,res1,res2); //res1.output(); //res2.output(); double a,b,c,x1,x2; getline(light,res1,a,b,c); x1 = (-c)/a; getline(light,res2,a,b,c); x2 = (-c)/a; nodes[i].lx = min(x1,x2); nodes[i].rx = max(x1,x2); } sort(nodes,nodes+n,cmp); double leftx = nodes[0].lx; double rightx = nodes[0].rx; printf("%.2lf",nodes[0].lx); double prevy=nodes[0].rx; for(int i=1;i<n;i++) { if(nodes[i].lx>prevy) { printf(" %.2lf\n%.2lf",prevy,nodes[i].lx); } if(prevy<nodes[i].rx) prevy=nodes[i].rx; } printf(" %.2lf\n",prevy); putchar('\n'); } return 0; } /*poj 1329*/ //求三角形的外接圆,裸的三角形外接圆,比较水,只要控制输出就行了 #include <cstdio> #include <cstring> #include <cmath> using namespace std; #define sqr(a) ( (a*a) ) #define EPS 1e-6 struct Point{ double x,y; Point(){} Point(double _x,double _y):x(_x),y(_y){} bool input(){ if(scanf("%lf%lf",&x,&y)!= EOF)return 1; return 0; } }; inline double difcross(Point a,Point b,Point c){ return (b.x-a.x)*(c.y-a.y)-(c.x-a.x)*(b.y-a.y); } inline double pdis(Point a,Point b){ return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y)); } inline double trarea(Point a,Point b,Point c){ return fabs(difcross(a,b,c))/2.0; } inline Point get_out_circle(Point a,Point b,Point c){ double c1,c2,xa,xb,xc,ya,yb,yc; Point o; xa = a.x,xb = b.x,xc = c.x; ya = a.y,yb = b.y,yc = c.y; c1 = (sqr(xa)+sqr(ya)-sqr(xb)-sqr(yb))/2.0; c2 = (sqr(xa)+sqr(ya)-sqr(xc)-sqr(yc))/2.0; o.x = (c1*(ya-yc)-c2*(ya-yb))/((xa-xb)*(ya-yc)-(xa-xc)*(ya-yb)); o.y = (c1*(xa-xc)-c2*(xa-xb))/((ya-yb)*(xa-xc)-(ya-yc)*(xa-xb)); return o; } inline double get_out_r(Point a,Point b,Point c){ double ab = pdis(a,b),bc = pdis(b,c),ca = pdis(c,a),s = trarea(a,b,c); return ab*bc*ca/(4*s); } int main(){ Point a,b,c; while(a.input()){ b.input(); c.input(); Point o = get_out_circle(a,b,c); double r = get_out_r(a,b,c); bool flagx,flagy; if(o.x > EPS)flagx = 1; else flagx = 0; if(o.y > EPS)flagy = 1; else flagy = 0; printf("(x "); if(flagx)printf("- %.3lf)^2 + ",o.x); else printf("+ %.3lf)^2 + ",-o.x); printf("(y "); if(flagy)printf("- %.3lf)^2 ",o.y); else printf("+ %.3lf)^2 ",-o.y); printf("= %.3lf^2\n",r); printf("x^2 + y^2 "); if(flagx)printf("- %.3lfx ",2*o.x); else printf("+ %.3lfx ",-2*o.x); if(flagy)printf("- %.3lfy ",2*o.y); else printf("+ %.3lfy ",-2*o.y); double tmp = o.x*o.x+o.y*o.y-r*r; if(tmp > 0)printf("+ %.3lf = 0\n",tmp); else printf("- %.3lf = 0\n",-tmp); puts(""); } return 0; } /*POJ 2354 Titanic*/ //求球面上两个点的距离,给的是地理经纬坐标,以前没遇到过这种关于球的问题 //由于这个题的输入输出比较烦,所以就换了两个同样的问题,输入输出比较简单一点的,和此题一样 /* *假设地球是球体, *设地球上某点的经度为lambda,纬度为phi, *则这点的空间坐标是 *x=cos(phi)*cos(lambda) *y=cos(phi)*sin(lambda) *z=sin(phi) *设地球上两点的空间坐标分别为(x1,y1,z1),(x2,y2,z2) *直线距离即为R*sqrt((x2-x1)*(x2-x1)+(y2-y1)*(y2-y1)+(z2-z1)*(z2-z1)), *则它们的夹角为 A = acos(x1 * x2 + y1 * y2 + z1 * z2) *球面距离为 A*R/2(R 即地球半径) */ /*poj 2587*/ #include<cmath> #include<cstdio> #include<cstring> #include<iostream> #include<algorithm> using namespace std; const int M =1005; const double P=acos(-1.0); struct air { double lon,lat,j,w; double x,y,z; }a[M]; int n,ans; double minn,maxn; double dist(air a1,air a2) { return (a1.x-a2.x)*(a1.x-a2.x)+(a1.y-a2.y)*(a1.y-a2.y)+(a1.z-a2.z)*(a1.z-a2.z); } int main() { scanf("%d",&n); for(int i=0;i<n;i++) { scanf("%lf%lf",&a[i].lat,&a[i].lon); a[i].j=a[i].lon; a[i].w=a[i].lat; a[i].lat*=P/180; a[i].lon*=P/180; a[i].x=cos(a[i].lat)*cos(a[i].lon); a[i].y=cos(a[i].lat)*sin(a[i].lon); a[i].z=sin(a[i].lat); } minn=999999.0; for(int i=0;i<n;i++) { maxn=0; for(int j=0;j<n;j++) { double temp=dist(a[i],a[j]); if(temp>maxn)maxn=temp; } if(minn>maxn) { minn=maxn; ans=i; } } printf("%.2lf %.2lf\n",a[ans].w,a[ans].j); return 0; } /*poj 3407*/ #include<cmath> #include<cstdio> #include<cstring> #include<iostream> #include<algorithm> using namespace std; const double P=acos(-1.0); struct node { double x, y, z; double lat,lon; }; int main() { double lat1, latm1, lon1, lonm1; double lat2, latm2, lon2, lonm2; node p1, p2; char dir1, dir2; while(scanf("%lf %lf %c %lf %lf %c",&lat1,&latm1,&dir1,&lon1,&lonm1,&dir2)!=EOF){ p1.lat=(lat1+latm1/60)* P/180; p1.lon=(lon1 +lonm1/60)*P/180; if(dir1=='S')p1.lat*=-1.0; if(dir2=='W')p1.lon*=-1.0; p1.x=cos(p1.lat)*cos(p1.lon); p1.y=cos(p1.lat)*sin(p1.lon); p1.z=sin(p1.lat); scanf("%lf %lf %c %lf %lf %c",&lat2,&latm2,&dir1,&lon2,&lonm2,&dir2); p2.lat=(lat2+latm2/60)*P/180; p2.lon=(lon2+lonm2/60)*P/180; if(dir1=='S')p2.lat*=-1.0; if(dir2=='W')p2.lon*=-1.0; p2.x=cos(p2.lat)*cos(p2.lon); p2.y=cos(p2.lat)*sin(p2.lon); p2.z=sin(p2.lat); double angle=acos(p1.x*p2.x+p1.y*p2.y+p1.z*p2.z); printf("%.3lf\n",angle*6370.0); } return 0; } /*POJ 1106 Transmitters*/ //这题什么也不用,直接枚举就行了,只用了一个叉积 #include <cstdio> #include <cstring> #include <cmath> #include <algorithm> using namespace std; #define EPS 1e-16 #define feq(a,b) (fabs((a)-(b))<EPS)//a==b #define fbg(a,b) ((a) > EPS+(b)) //a > b #define fsm(a,b) ((b) > EPS+(a)) //a < b #define fbgeq(a,b) ((a) >= (b)-EPS) //a >= b #define fsmeq(a,b) ((b) >= (a)-EPS) //a <= b const int MAXN = 155; struct Point{ double x,y; Point(){} Point(double _x,double _y):x(_x),y(_y){} bool input(){ if(scanf("%lf%lf",&x,&y)!=EOF)return 1; return 0; } }; inline double pdis(Point a,Point b){ return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y)); } inline double difcross(Point a,Point b,Point c){ return (b.x-a.x)*(c.y-a.y)-(c.x-a.x)*(b.y-a.y); } Point points[MAXN]; Point o; double r; int main(){ while(o.input()){ scanf("%lf",&r); if(fsm(r,0))break; int n; scanf("%d",&n); int top = 0; Point tmp; while(n --){ tmp.input(); if(fbg(pdis(tmp,o),r))continue; points[top++] = tmp; } int ans = 0,cnt; for(int i = 0; i < top; ++i){ Point tt = Point(2*o.x-points[i].x,2*o.y-points[i].y); cnt = 0; for(int j = 0; j < top; ++j) if(fsmeq(difcross(points[i],tt,points[j]),0))cnt++; if(ans < cnt)ans = cnt; } printf("%d\n",ans); } return 0; } /*http://www.codeforces.com/contest/32/problem/E*/ //补充一个线段求交的题,要考虑各种情况,特别是共线的时候对两种不同的线段采取不同的策略。 #include <cstdio> #include <cstring> #include <cmath> using namespace std; #define EPS 1e-8 #define max(a,b) ((a)>(b) ? (a) : (b)) #define min(a,b) ((a)<(b) ? (a) : (b)) #define feq(a,b) (fabs((a)-(b))<EPS)//a==b #define fbg(a,b) ((a) > EPS+(b)) //a > b #define fsm(a,b) ((b) > EPS+(a)) //a < b #define fbgeq(a,b) ((a) >= (b)-EPS) //a >= b #define fsmeq(a,b) ((b) >= (a)-EPS) //a <= b #define sqr(a) ((a)*(a)) struct Point{ double x,y; Point(){} Point(double _x,double _y):x(_x),y(_y){} void input(){ scanf("%lf%lf",&x,&y); } }; struct Segment{ Point a,b; Segment(){} Segment(Point _a,Point _b):a(_a),b(_b){} }; struct Line{ double a,b,c; }; Point p1,p2,rp2; Segment wall,mirr; inline double dotcross(Point a,Point b,Point c){ return (b.x-a.x)*(c.x-a.x)+(b.y-a.y)*(c.y-a.y); } inline double sqrpdis(Point a,Point b){ return (a.x - b.x)*(a.x - b.x)+(a.y - b.y)*(a.y - b.y); } inline double difcross(Point a,Point b,Point c){ return (b.x-a.x)*(c.y-a.y)-(c.x-a.x)*(b.y-a.y); } inline Point Perpendicular(Point p, Segment s) { Point tp; double r = dotcross( s.a,p, s.b)/sqrpdis(s.a,s.b); tp.x=s.a.x+r*(s.b.x-s.a.x); tp.y=s.a.y+r*(s.b.y-s.a.y); return Point(2*tp.x-p.x,2*tp.y-p.y); } inline bool SegIntersect(Segment s1,Segment s2) { double mxs1x = max(s1.a.x,s1.b.x), mns1x = min(s1.a.x,s1.b.x); double mxs2x = max(s2.a.x,s2.b.x), mns2x = min(s2.a.x,s2.b.x); double mxs1y = max(s1.a.y,s1.b.y), mns1y = min(s1.a.y,s1.b.y); double mxs2y = max(s2.a.y,s2.b.y), mns2y = min(s2.a.y,s2.b.y); return fsmeq(difcross(s1.a,s1.b,s2.a)*difcross(s1.a,s1.b,s2.b), 0)&& fsmeq(difcross(s2.a,s2.b,s1.a)*difcross(s2.a,s2.b,s1.b), 0)&& fbgeq(mxs1x, mns2x)&&fbgeq(mxs2x, mns1x) && fbgeq(mxs1y, mns2y)&&fbgeq(mxs2y, mns1y); } inline bool check(){ Segment s = Segment(p1,p2); if(!SegIntersect(s,wall)){ if(!SegIntersect(s,mirr)|| (feq(difcross(mirr.a,p1,p2),0)&&feq(difcross(mirr.b,p1,p2),0))) return 1; } return 0; } inline void getline(Point x,Point y,Line &l){ l.a = y.y - x.y; l.b = x.x - y.x; l.c = y.x * x.y - x.x * y.y; } bool line_intersect(Line l1,Line l2,Point &p) { double d=l1.a*l2.b-l2.a*l1.b; if (feq(d, 0)) return 0; p.x = (l2.c*l1.b-l1.c*l2.b)/d; p.y = (l2.a*l1.c-l1.a*l2.c)/d; return true; } inline bool check2(){ if( fsm(difcross(mirr.a, mirr.b, p1)*difcross(mirr.a, mirr.b, p2), 0) )return 0; Point p3;Line l1,l2; getline(mirr.a,mirr.b,l2); double a1 = l2.a,b1 = l2.b,c1 = l2.c; p3.x = ((sqr(b1) - sqr(a1)) * p2.x - 2 * a1 * b1 * p2.y - 2 * a1 * c1) / (sqr(a1) + sqr(b1)); p3.y = ((sqr(a1) - sqr(b1)) * p2.y - 2 * a1 * b1 * p2.x - 2 * b1 * c1) / (sqr(a1) + sqr(b1)); rp2 = p3; Segment s = Segment(p1,rp2); Segment s1 = Segment(p2,rp2); Point tt; getline(p1,rp2,l1); line_intersect(l1,l2,tt); if (! (tt.x >= min(mirr.a.x, mirr.b.x) && tt.x <= max(mirr.a.x, mirr.b.x) && tt.y >= min(mirr.a.y, mirr.b.y) && tt.y <= max(mirr.a.y, mirr.b.y))) return 0; s1 = Segment(p2,tt); if(SegIntersect(s1,wall))return 0; s1 = Segment(p1,tt); if(SegIntersect(s1,wall))return 0; return 1; } int main(){ p1.input(); p2.input(); wall.a.input(); wall.b.input(); mirr.a.input(); mirr.b.input(); if(check()){ printf("YES\n"); return 0; } if(check2()) printf("YES\n"); else printf("NO\n"); } /*POJ 1673 EXOCENTER OF A TRIANGLE*/ //求三角形垂心,输出时要加eps,不然wa #include <cstdio> #include <cstring> #include <cmath> using namespace std; #define EPS 1e-8 struct Point{ double x,y; Point(){} Point(double _x,double _y):x(_x),y(_y){} void input(){ scanf("%lf%lf",&x,&y); } }; struct Line{ double a,b,c; Line(){} Line(double _a,double _b,double _c):a(_a),b(_b),c(_c){} }; inline bool line_intersect(Line l1,Line l2,Point &p) { double d=l1.a*l2.b-l2.a*l1.b; if (fabs(d) <= EPS) return 0; p.x = (l2.c*l1.b-l1.c*l2.b)/d; p.y = (l2.a*l1.c-l1.a*l2.c)/d; return true; } inline double difcross(Point p0,Point p1,Point p2){ return (p1.x-p0.x)*(p2.y-p0.y)-(p2.x-p0.x)*(p1.y-p0.y); } inline double pdis(Point a,Point b){ return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y)); } inline void getline(Point a,Point b,Point c,Line &l){ l.a = c.x - b.x; l.b = c.y - b.y; l.c = (b.y-c.y)*a.y-(c.x-b.x)*a.x; if(l.a < -EPS){ l.a = -l.a; l.b = -l.b; l.c = -l.c; } } inline double trarea(Point a,Point b,Point c){ return fabs(difcross(a,b,c))/2.0; } inline Point GetChuiXin(Point a,Point b,Point c) { Line l1,l2; getline(a,b,c,l1); getline(c,a,b,l2); Point ans; line_intersect(l1,l2,ans); return ans; } int main(){ Point a,b,c,o; int cas; scanf("%d",&cas); while(cas --){ a.input(); b.input(); c.input(); o = GetChuiXin(a,b,c); printf("%.4lf %.4lf\n",o.x+EPS,o.y+EPS); } return 0; } 八、旋转卡壳 要理解旋转卡壳到底是个什么东西,最经典的问题就是求凸包的最近距离 /*POJ 2187 Beauty Contest*/ //该题数据比较水,直接求凸包然后枚举也能过,但有些题就必须用卡壳了,比如说: //http://acm.tju.edu.cn/toj/showp2847.html这一题考的就是卡壳,不用卡壳是一定超时的。 ///由于这个东西相对比较难,单独拉到下一篇文章(下一篇文章,旋转卡壳卡卡~)里 九。其他问题 /*POJ 1981 Circle and Points*/ //问单位圆最多覆盖几个点。枚举,取任意两点求出圆心,然后查询圆内有多少个点,取最大值即可 #include<cmath> #include<cstdio> #include<cstring> using namespace std; #define eps 1e-6 struct node { double x,y; }p[305],center; int n,ans,maxn; inline double dist(node a,node b) { return (a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y); } inline void cer(node p1,node p2) { node p3,mid; double r1,r2,angle; p3.x=p1.x-p2.x; p3.y=p1.y-p2.y; mid.x=(p1.x+p2.x)/2; mid.y=(p1.y+p2.y)/2; r1=dist(p1,mid); r2=sqrt(1-r1); angle=atan(-p3.x/p3.y); center.x=mid.x+r2*cos(angle); center.y=mid.y+r2*sin(angle); } int main() { while(scanf("%d",&n),n) { for(int i=0;i<n;i++) scanf("%lf%lf",&p[i].x,&p[i].y); maxn=1; for(int i=0;i<n;i++) for(int j=i+1;j<n;j++) { if(dist(p[i],p[j])>4)continue; ans=0; cer(p[i],p[j]); for(int k=0;k<n;k++) { double temp=dist(p[k],center); if(temp<=1+eps)ans++; } if(ans>maxn)maxn=ans; } printf("%d\n",maxn); } return 0; } 至此,计算几何题目推荐的第一部分完结,赞美神,赞美主