很多题,很多代码:一、点,线,面,形基本关系,点积叉积的理解/*poj2318toys*///判断箱子每一个块内有多少个玩具,可以用叉积的性质找到玩具的位置,过程采用二分查找。#include <cstdio>#include <cstring>using namespace std;#define EPS 1e-8const 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-8inline 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-8struct 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 99999999const 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 1000000000const 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-8int 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 <= bstruct 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 <= bconst 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 <= bconst 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 <= bconst 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 <= bconst 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 <= bconst 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 <= bconst 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 <= bconst 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,一律输出NO2. 所有点共线,NO3. 凸包上每条边上至少有三点,否则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 <= bconst 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-6struct 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 <= bconst 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-8struct 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-6struct 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;}至此,计算几何题目推荐的第一部分完结,赞美神,赞美主