计算几何基础部分大部分题目只要有模板就能过了,下面的题也大都是贴模板过的。
HDU 1086:
http://acm.hust.edu.cn/vjudge/problem/visitOriginUrl.action?id=17612
给出 n 条线段,求其中相交的对数。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| #include<cstdio> struct Line{ double x1,y1,x2,y2; }a[110]; bool solve(Line a,Line b){ if(((a.x1-b.x1)*(a.y2-b.y1)-(a.x2-b.x1)*(a.y1-b.y1))*((a.x1-b.x2)*(a.y2-b.y2)-(a.x2-b.x2)*(a.y1-b.y2))>0)return false; if(((b.x1-a.x1)*(b.y2-a.y1)-(b.x2-a.x1)*(b.y1-a.y1))*((b.x1-a.x2)*(b.y2-a.y2)-(b.x2-a.x2)*(b.y1-a.y2))>0)return false; return true; } int main(){ int n; while(~scanf("%d",&n)&&n){ int cnt=0; for(int i=0;i<n;++i) scanf("%lf%lf%lf%lf",&a[i].x1,&a[i].y1,&a[i].x2,&a[i].y2); for(int i=0;i<n;++i) for(int j=i+1;j<n;++j) if(solve(a[i],a[j])) ++cnt; printf("%d\n",cnt); } return 0; }
|
HDU 1115:
http://acm.hust.edu.cn/vjudge/problem/visitOriginUrl.action?id=16214
按顺序给出多个点,求给出点的的重心坐标。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36
| #include<cstdio> using namespace std; const int maxn=1000010; struct node{ double x,y; }a[maxn]; node gravity(node *p, int n) { double area = 0; node center; center.x = 0; center.y = 0; for (int i = 0; i < n-1; i++) { area += (p[i].x*p[i+1].y - p[i+1].x*p[i].y)/2; center.x += (p[i].x*p[i+1].y - p[i+1].x*p[i].y) * (p[i].x + p[i+1].x); center.y += (p[i].x*p[i+1].y - p[i+1].x*p[i].y) * (p[i].y + p[i+1].y); } area += (p[n-1].x*p[0].y - p[0].x*p[n-1].y)/2; center.x += (p[n-1].x*p[0].y - p[0].x*p[n-1].y) * (p[n-1].x + p[0].x); center.y += (p[n-1].x*p[0].y - p[0].x*p[n-1].y) * (p[n-1].y + p[0].y); center.x /= 6*area; center.y /= 6*area; return center; } int main(){ int t;scanf("%d",&t); while(t--){ int n;scanf("%d",&n); for(int i=0;i<n;++i) scanf("%lf%lf",&a[i].x,&a[i].y); node ans=gravity(a,n); printf("%.2lf %.2lf\n",ans.x,ans.y); } return 0; }
|
HDU 2036:
http://acm.hust.edu.cn/vjudge/problem/visitOriginUrl.action?id=17490
按顺序给出多个点的坐标,求所构成的凸多边形面积。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| #include<cstdio> #include<cmath> const int maxn=110; struct point{ double x,y; }a[maxn]; double area_polygon(int n,point* p){ double s1=0,s2=0; for(int 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; } int main(){ int n; while(~scanf("%d",&n)&&n){ for(int i=0;i<n;++i) scanf("%lf%lf",&a[i].x,&a[i].y); printf("%.1lf\n",area_polygon(n,a)); } return 0; }
|
HDU 2108:
http://acm.hust.edu.cn/vjudge/problem/visitOriginUrl.action?id=18631
按顺序给出多个点,判断形成的是凸多边形,还是凹多边形。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
| #include<cstdio> #include<cmath> const int maxn=110; struct point{ double x,y; }a[maxn]; #define eps 1e-8 #define _sign(x) ((x)>eps?1:((x)<-eps?2:0)) 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); } int is_convex(int n,point* p){ int i,s[3]={1,1,1}; for (i=0;i<n&&s[1]|s[2];i++) s[_sign(xmult(p[(i+1)%n],p[(i+2)%n],p[i]))]=0; return s[1]|s[2]; } int main(){ int n; while(~scanf("%d",&n)&&n){ for(int i=0;i<n;++i) scanf("%lf%lf",&a[i].x,&a[i].y); puts(is_convex(n,a)?"convex":"concave"); } return 0; }
|
HDU 1392:
http://acm.hust.edu.cn/vjudge/problem/visitOriginUrl.action?id=18630
给出多个点,求凸包的周长。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52
| #include<cstdio> #include<cstring> #include<cmath> #include<algorithm> using namespace std; const int maxn=110; struct point{ double x,y; }a[maxn],b[maxn]; bool mult(point p0,point p1,point p2){ return (p1.x-p0.x)*(p2.y-p0.y)>=(p2.x-p0.x)*(p1.y-p0.y); } bool operator<(const point &p1,const point &p2){ return p1.y<p2.y||(p1.y==p2.y&&p1.x<p2.x); } int graham(point pnt[],int n,point res[]){ int i,len,top=1; sort(pnt,pnt+n); if(n==0) return 0; res[0]=pnt[0]; if(n==1) return 1; res[1]=pnt[1]; if(n==2) return 2; res[2]=pnt[2]; for(i=2;i<n;i++){ while(top&&mult(pnt[i],res[top],res[top-1])) top--; res[++top]=pnt[i]; } len=top;res[++top]=pnt[n-2]; for(i=n-3;i>=0;i--){ while(top!=len&&mult(pnt[i],res[top],res[top-1])) top--; res[++top]=pnt[i]; } return top; } int main(){ int n; while(~scanf("%d",&n)&&n){ memset(a,0,sizeof(a)); memset(b,0,sizeof(b)); for(int i=0;i<n;++i) scanf("%lf%lf",&a[i].x,&a[i].y); int k=graham(a,n,b); double ans=0; for(int i=0;i<k-1;++i) ans+=sqrt((b[i].x-b[i+1].x)*(b[i].x-b[i+1].x)+(b[i].y-b[i+1].y)*(b[i].y-b[i+1].y)); if(k>2) ans+=sqrt((b[k-1].x-b[0].x)*(b[k-1].x-b[0].x)+(b[k-1].y-b[0].y)*(b[k-1].y-b[0].y)); printf("%.2lf\n",ans); } return 0; }
|
HDU 1348:
http://acm.hust.edu.cn/vjudge/problem/visitOriginUrl.action?id=32007
求凸包每个顶点向外延伸半径为1的圆后所得图形的周长。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55
| #include<cstdio> #include<cstring> #include<cmath> #include<algorithm> using namespace std; const int maxn=1010; struct point{ double x,y; }a[maxn],b[maxn]; bool mult(point p0,point p1,point p2){ return (p1.x-p0.x)*(p2.y-p0.y)>=(p2.x-p0.x)*(p1.y-p0.y); } bool operator<(const point &p1,const point &p2){ return p1.y<p2.y||(p1.y==p2.y&&p1.x<p2.x); } int graham(point pnt[],int n,point res[]){ int i,len,top=1; sort(pnt,pnt+n); if(n==0) return 0; res[0]=pnt[0]; if(n==1) return 1; res[1]=pnt[1]; if(n==2) return 2; res[2]=pnt[2]; for(i=2;i<n;i++){ while(top&&mult(pnt[i],res[top],res[top-1])) top--; res[++top]=pnt[i]; } len=top;res[++top]=pnt[n-2]; for(i=n-3;i>=0;i--){ while(top!=len&&mult(pnt[i],res[top],res[top-1])) top--; res[++top]=pnt[i]; } return top; } int main(){ int t;scanf("%d",&t); while(t--){ int n,l;scanf("%d%d",&n,&l); memset(a,0,sizeof(a)); memset(b,0,sizeof(b)); for(int i=0;i<n;++i) scanf("%lf%lf",&a[i].x,&a[i].y); int k=graham(a,n,b); double ans=0; for(int i=0;i<k-1;++i) ans+=sqrt((b[i].x-b[i+1].x)*(b[i].x-b[i+1].x)+(b[i].y-b[i+1].y)*(b[i].y-b[i+1].y)); if(k>2) ans+=sqrt((b[k-1].x-b[0].x)*(b[k-1].x-b[0].x)+(b[k-1].y-b[0].y)*(b[k-1].y-b[0].y)); ans+=2*acos(-1)*l; printf("%.0lf\n",ans); if(t) printf("\n"); } return 0; }
|
HDU 2150:
http://acm.hust.edu.cn/vjudge/problem/visitOriginUrl.action?id=31178
给出多条线段,判断有无相交线段。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40
| #include<cstdio> struct Line{ double x1,y1,x2,y2; Line(double x1=0,double y1=0,double x2=0,double y2=0):x1(x1),y1(y1),x2(x2),y2(y2){} }; struct node{ int k; Line l[110]; }a[33]; bool solve(Line a,Line b){ if(((a.x1-b.x1)*(a.y2-b.y1)-(a.x2-b.x1)*(a.y1-b.y1))*((a.x1-b.x2)*(a.y2-b.y2)-(a.x2-b.x2)*(a.y1-b.y2))>0)return false; if(((b.x1-a.x1)*(b.y2-a.y1)-(b.x2-a.x1)*(b.y1-a.y1))*((b.x1-a.x2)*(b.y2-a.y2)-(b.x2-a.x2)*(b.y1-a.y2))>0)return false; return true; } int main(){ int n; while(~scanf("%d",&n)){ for(int i=0;i<n;++i){ scanf("%d",&a[i].k); --a[i].k; double px1,py1; scanf("%lf%lf",&px1,&py1); for(int j=0;j<a[i].k;++j){ double x1,y1; scanf("%lf%lf",&x1,&y1); a[i].l[j]=Line(px1,py1,x1,y1); px1=x1,py1=y1; } } bool flag=false; for(int i=0;i<n;++i) for(int j=i+1;j<n;++j) for(int k=0;k<a[i].k;++k) for(int l=0;l<a[j].k;++l) if(solve(a[i].l[k],a[j].l[l])) {flag=true;goto END;} END: printf("%s\n",flag?"Yes":"No"); } return 0; }
|
HDU 1558:
http://acm.hust.edu.cn/vjudge/problem/visitOriginUrl.action?id=19356
给出多条线段,输出有几个连通块。判断线段相交之后,用并查集求解。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47
| #include<iostream> #include<string> using namespace std; const int maxn=1010; int p[maxn],num[maxn]; struct Line{ double x1,y1,x2,y2; Line(double x1=0,double y1=0,double x2=0,double y2=0):x1(x1),y1(y1),x2(x2),y2(y2){} }a[maxn];
bool solve(Line a,Line b){ if(((a.x1-b.x1)*(a.y2-b.y1)-(a.x2-b.x1)*(a.y1-b.y1))*((a.x1-b.x2)*(a.y2-b.y2)-(a.x2-b.x2)*(a.y1-b.y2))>0)return false; if(((b.x1-a.x1)*(b.y2-a.y1)-(b.x2-a.x1)*(b.y1-a.y1))*((b.x1-a.x2)*(b.y2-a.y2)-(b.x2-a.x2)*(b.y1-a.y2))>0)return false; return true; } int find(int x){ return p[x]==x?x:p[x]=find(p[x]); } void merge(int x,int y){ int fx=find(x),fy=find(y); if(fx!=fy) p[fx]=fy,num[fy]+=num[fx]; return; } int main(){ int t;cin>>t; while(t--){ int n,cnt=0;cin>>n; for(int i=0;i<n;++i){ string s;cin>>s; if(s=="P"){ ++cnt,p[cnt]=cnt,num[cnt]=1; Line& k=a[cnt]; cin>>k.x1>>k.y1>>k.x2>>k.y2; for(int j=1;j<cnt;++j){ if(find(j)!=find(cnt)&&solve(a[j],k)) merge(cnt,j); } } else if(s=="Q"){ int k;cin>>k; cout<<num[find(k)]<<endl; } } if(t) cout<<endl; } return 0; }
|
HDU 1785:
http://acm.hust.edu.cn/vjudge/problem/visitOriginUrl.action?id=30271
就是结构体重载运算符的题。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| #include<cstdio> #include<algorithm> const int maxn=110; struct node{ double x,y; bool operator < (const node& rhs) const { return x*rhs.y>rhs.x*y; } }a[maxn]; int main(){ int n; while(~scanf("%d",&n)&&n>=0){ for(int i=0;i<n;++i) scanf("%lf%lf",&a[i].x,&a[i].y); std::sort(a,a+n); for(int i=0;i<n;++i) printf("%.1lf %.1lf%c",a[i].x,a[i].y,i==n-1?'\n':' '); } return 0; }
|
** 本文迁移自我的CSDN博客,格式可能有所偏差。 **