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 最大三角形
模板凸包,然后枚举凸包上的三点即可求叉积即可