7.1.1 HDU2108 Shape of HDU
判断凸多边形,每连续三个点之间求叉积判断即可
7.1.2 HDU1086 You can Solve a Geometry Problem too
判断线段相交,模板题,参考吉大模板
7.1.3 HDU1115 Lifting the Stone
多边形重心,模板题,参考吉大模板
7.1.4 HDU1392 Surround the Trees
凸包,计算周长
#include <cstdio> #include <string> #include <math.h> #include <string.h> #include <stdlib.h> #include <iostream> #include <algorithm> using namespace std; struct point{ double x,y; }pnt[110],res[110]; int n,ind; //小于0,说明P0P1>P0P2(极角) double mult(point p0,point p1,point p2){ return (p2.y-p0.y)*(p1.x-p0.x)-(p1.y-p0.y)*(p2.x-p0.x); } double dis(point px,point py){ return sqrt((py.y-px.y)*(py.y-px.y)+(py.x-px.x)*(py.x-px.x)); } bool cmp(const point &a,const point &b){ double t=mult(pnt[0],a,b); if(t!=0)return t>0; return dis(pnt[0],a)<dis(pnt[0],b); } double graham(){ //当点数不多于3个的时候,直接返回答案 if(n==1)return 0; if(n==2)return dis(pnt[0],pnt[1]); if(n==3)return dis(pnt[0],pnt[1])+dis(pnt[1],pnt[2])+dis(pnt[2],pnt[0]); //寻找y坐标最小的点(y坐标相同取x最小) ind=0; for(int i=1;i<n;i++){ if(pnt[i].y<pnt[ind].y||pnt[i].y==pnt[ind].y&&pnt[i].x<pnt[ind].x)ind=i; } if(ind!=0){ point tmp=pnt[0]; pnt[0]=pnt[ind]; pnt[ind]=tmp; } //按照极角从小到大排序,相同时按照距离第一个点距离排序 sort(pnt+1,pnt+n,cmp); //加点 int top=1; res[0]=pnt[0],res[1]=pnt[1]; for(int i=2;i<n;i++){ while(mult(res[top-1],res[top],pnt[i])<0)top--; res[++top]=pnt[i]; } //计算周长 double r=dis(res[0],res[top]); for(int i=1;i<=top;i++){ r+=dis(res[i],res[i-1]); } return r; } int main(){ while(scanf("%d",&n),n){ for(int i=0;i<n;i++)scanf("%lf%lf",&pnt[i].x,&pnt[i].y); printf("%.2lf\n",graham()); } return 0; }
7.1.5 HDU1577 WisKey的眼神
当直角三角形两直角边互质时,斜边不会经过其它整点(通过相似三角形可以证明)
gcd(fabs(sx-px),fabs(sy-py))==1?"Yes\n":"No\n"
7.1.6 HDU1147 Pick-up sticks
o(n^2)的枚举,理论超时却能过这题,数据弱?还是break的作用使实际复杂度低于O(n^2)?
#include <cstdio> #include <algorithm> #define INF 1e20 #define eps 1e-10 #define MAXN 100010 using namespace std; struct point{double x,y;}; struct line{point a,b;int top;}l[MAXN]; int n; 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 cross(line u,line v){ return ((max(u.a.x,u.b.x)>=min(v.a.x,v.b.x))&& (max(v.a.x,v.b.x)>=min(u.a.x,u.b.x))&& (max(u.a.y,u.b.y)>=min(v.a.y,v.b.y))&& (max(v.a.y,v.b.y)>=min(u.a.y,u.b.y))&& (xmult(v.a,u.b,u.a)*xmult(u.b,v.b,u.a)>=0)&& (xmult(u.a,v.b,v.a)*xmult(v.b,u.b,v.a)>=0)); } int main(){ while(scanf("%d",&n),n){ for(int i=0;i<n;i++){ scanf("%lf%lf%lf%lf",&l[i].a.x,&l[i].a.y,&l[i].b.x,&l[i].b.y); } for(int i=0;i<n;i++){ int yes=1; l[i].top=0; for(int j=i+1;j<n;j++){ if(cross(l[i],l[j])){yes=0;break;} } if(yes)l[i].top=1; } printf("Top sticks: "); int ind=0; for(;ind<n;ind++)if(l[ind].top==1){printf("%d",ind+1);break;} for(ind++;ind<n;ind++)if(l[ind].top==1){printf(", %d",ind+1);} printf(".\n"); } return 0; }
7.1.7 HDU2215 Maple trees
求最大外接圆,先求出凸包上的点,再每次枚举三个点,当钝角三角形时,r=最大边/2,否则r=c/(2sin(a,b))=a*b*c/(2(axb)).求出最大R即可
7.1.8 HDU2202 最大三角形
模板凸包,然后枚举凸包上的三点即可求叉积即可