1.poj1113 Wall
题目:http://poj.org/problem?id=1113
题意:用一条线把若干个点包起来,并且线距离任何一个点的距离都不小于r。求这条线的最小距离是多少?
分析:这道题的答案是凸包周长加上一个圆周长,即包围凸包的一个圆角多边形,但是没弄明白那些圆角加起来为什么恰好是一个圆。每个圆角是以凸包对应的顶点为圆心,给定的L为半径,与相邻两条边的切点之间的一段圆弧。每个圆弧的两条半径夹角与对应的凸包的内角互补。假设凸包有n条边,则所有圆弧角之和为180°*n-180°*(n-2)=360°。故,围墙周长为=n条平行于凸包的线段+n条圆弧的长度=凸包周长+围墙离城堡距离L为半径的圆周长。
1 #include<iostream> 2 #include<cstring> 3 #include<algorithm> 4 #include<cmath> 5 using namespace std; 6 const int maxn=1010; 7 const double eps=1e-8; 8 const double pi=acos(-1.0); 9 inline double sqr(double x){return x*x;} 10 int sgn(double x){ 11 if (fabs(x)<eps) return 0; 12 if (x<0) return -1; 13 return 1; 14 } 15 struct point{ 16 double x,y; 17 point(){} 18 point(double _x,double _y):x(_x),y(_y){} 19 //判断两点相同 20 bool operator ==(const point &b) const{ 21 return sgn(x-b.x)==0 && sgn(y-b.y)==0; 22 } 23 // 24 point operator -(const point &b) const{ 25 return point(x-b.x,y-b.y); 26 } 27 //叉积 28 double operator ^(const point &b) const{ 29 return x*b.y-y*b.x; 30 } 31 //点积 32 double operator *(const point &b) const{ 33 return x*b.x+y*b.y; 34 } 35 //重载小于号 (求最左下角的点 36 bool operator <(const point &b)const{ 37 return sgn(x-b.x)==0 ? sgn(y-b.y)<0 : x<b.x; 38 } 39 }; 40 struct line{ 41 point s,e; 42 line(){} 43 line(point _s,point _e):s(_s),e(_e){} 44 }; 45 double dis(point a,point b){ 46 return sqrt(sqr(a.x-b.x)+sqr(a.y-b.y)); 47 } 48 struct polygon{ 49 int n; 50 point p[maxn]; 51 line l[maxn]; 52 void add(point q){ 53 p[n++]=q; 54 } 55 void getline(){ 56 for (int i=0;i<n;i++) 57 l[i]=line(p[i],p[(i+1)%n]); 58 } 59 struct cmp{ 60 point p; 61 cmp(const point &p0):p(p0){} 62 bool operator ()(const point &aa,const point &bb){ 63 point a=aa,b=bb; 64 int d=sgn((a-p)^(b-p)); 65 if (d==0){ 66 return sgn(dis(a,p)-dis(b,p))<0; 67 } 68 return d>0; 69 } 70 }; 71 //极角排序 先找到左下角的点 72 //重载好point的'<' 73 void norm(){ 74 point mi=p[0]; 75 for (int i=1;i<n;i++) mi=min(mi,p[i]); 76 sort(p,p+n,cmp(mi)); 77 } 78 //得到凸包,点编号为0--n-1 79 void Graham(polygon &convex){ 80 norm(); 81 int &top=convex.n; 82 top=0; 83 if (n==1){ 84 top=1; convex.p[0]=p[0]; return ; 85 } 86 if (n==2){ 87 top=2; convex.p[0]=p[0]; convex.p[1]=p[1]; 88 if (convex.p[0]==convex.p[1]) top--; 89 return ; 90 } 91 convex.p[0]=p[0]; convex.p[1]=p[1]; top=2; 92 for (int i=2;i<n;i++){ 93 while (top>1 && sgn((convex.p[top-1]-convex.p[top-2])^(p[i]-convex.p[top-2]))<=0) top--; 94 convex.p[top++]=p[i]; 95 } 96 if (convex.n==2 && (convex.p[0]==convex.p[1])) convex.n--; 97 } 98 }; 99 polygon C; 100 int main(){ 101 int n,L; cin >> n >> L; 102 double x,y; 103 for (int i=0;i<n;i++){ 104 cin >> x >> y; 105 C.add(point(x,y)); 106 } 107 polygon ans; 108 C.Graham(ans); 109 ans.getline(); 110 double res=0; 111 for (int i=0;i<ans.n;i++) res+=dis(ans.l[i].s,ans.l[i].e); 112 res+=2*pi*L; 113 printf("%d\n",(int)(res+0.5)); 114 return 0; 115 }
(为了套板子,写的很繁琐)
2.poj2007 Scrambled Polygon
题目:http://poj.org/problem?id=2007
题意:求一个凸多边形的凸包。要求起始点为输入的第一个点。
分析:rt。
1 #include<iostream> 2 #include<algorithm> 3 #include<cstring> 4 #include<cmath> 5 using namespace std; 6 const double eps=1e-8; 7 const int maxn=55; 8 inline double sqr(int x){return x*x*1.0;} 9 int sgn(double x){ 10 if (fabs(x)<eps) return 0; 11 if (x<0) return -1; 12 return 1; 13 } 14 struct point{ 15 int x,y; 16 point(){} 17 point(int _x,int _y):x(_x),y(_y){} 18 bool operator ==(const point &b)const{ 19 return (x==b.x && y==b.y); 20 } 21 point operator -(const point &b)const{ 22 return point(x-b.x,y-b.y); 23 } 24 int operator ^(const point &b)const{ 25 return x*b.y-y*b.x; 26 } 27 int operator *(const point &b)const{ 28 return x*b.x+y*b.y; 29 } 30 //重载小于号 (求最左下角的点 31 bool operator <(const point &b)const{ 32 return sgn((x-b.x)*1.0)==0 ? sgn((y-b.y)*1.0)<0 : x<b.x; 33 } 34 }; 35 double dis(point a,point b){ 36 return sqrt(sqr(a.x-b.x)+sqr(a.y-b.y)); 37 } 38 struct polygon{ 39 int n; 40 point p[maxn]; 41 void add(point q){ 42 p[n++]=q; 43 } 44 struct cmp{ 45 point p; 46 cmp(const point &p0):p(p0){} 47 bool operator ()(const point &aa,const point &bb){ 48 point a=aa,b=bb; 49 int k=(a-p)^(b-p);int d; 50 if (k==0) d=0;else if (k<0) d=-1; else d=1; 51 if (d==0){ 52 return sgn(dis(a,p)-dis(b,p))<0; 53 } 54 return d>0; 55 } 56 }; 57 //极角排序 先找到左下角的点 58 //重载好point的'<' 59 void norm(){ 60 point mi=p[0]; 61 for (int i=1;i<n;i++) mi=min(mi,p[i]); 62 sort(p,p+n,cmp(mi)); 63 } 64 //得到凸包,点编号为0--n-1 65 void Graham(polygon &convex){ 66 norm(); 67 int &top=convex.n; 68 top=0; 69 if (n==1){ 70 top=1; convex.p[0]=p[0]; return ; 71 } 72 if (n==2){ 73 top=2; convex.p[0]=p[0]; convex.p[1]=p[1]; 74 if (convex.p[0]==convex.p[1]) top--; 75 return ; 76 } 77 convex.p[0]=p[0]; convex.p[1]=p[1]; top=2; 78 for (int i=2;i<n;i++){ 79 while (top>1 && sgn(((convex.p[top-1]-convex.p[top-2])^(p[i]-convex.p[top-2]))*1.0)<=0) top--; 80 convex.p[top++]=p[i]; 81 } 82 if (convex.n==2 && (convex.p[0]==convex.p[1])) convex.n--; 83 } 84 }; 85 polygon C; 86 int main(){ 87 int x,y; point p; 88 C.n=0; 89 cin >> x >> y; p=point(x,y); C.add(p); 90 while (cin >> x >> y) C.add(point(x,y)); 91 polygon ans; 92 C.Graham(ans); int k; 93 for (int i=0;i<ans.n;i++) if (ans.p[i]==p){k=i;break;} 94 for (int i=0;i<ans.n;i++){ 95 printf("(%d,%d)\n",ans.p[(k+i)%ans.n].x,ans.p[(k+i)%ans.n].y); 96 } 97 return 0; 98 }
3.
4
5.poj3348 Cows
题目:http://poj.org/problem?id=3348
题意:给出一些点圈出一个最大面积每50平方养一头牛问最多能养多少牛。
分析:凸包+多边形面积。
1 #include<iostream> 2 #include<cstring> 3 #include<algorithm> 4 #include<cmath> 5 using namespace std; 6 const int maxn=10005; 7 inline int sqr(int x){return x*x;} 8 struct point{ 9 int x,y; 10 point(){} 11 point(int _x,int _y):x(_x),y(_y){} 12 //判断两点相同 13 bool operator ==(const point &b) const{ 14 return x-b.x==0 && y-b.y==0; 15 } 16 // 17 point operator -(const point &b) const{ 18 return point(x-b.x,y-b.y); 19 } 20 //叉积 21 int operator ^(const point &b) const{ 22 return x*b.y-y*b.x; 23 } 24 //点积 25 int operator *(const point &b) const{ 26 return x*b.x+y*b.y; 27 } 28 //重载小于号 (求最左下角的点 29 bool operator <(const point &b)const{ 30 return x-b.x==0?y-b.y<0:x<b.x; 31 } 32 }; 33 struct line{ 34 point s,e; 35 line(){} 36 line(point _s,point _e):s(_s),e(_e){} 37 }; 38 int dis(point a,point b){ 39 return (int)sqrt(1.0*sqr(a.x-b.x)+1.0*sqr(a.y-b.y)); 40 } 41 struct polygon{ 42 int n; 43 point p[maxn]; 44 void add(point q){p[n++]=q;} 45 struct cmp{ 46 point p; 47 cmp(const point &p0):p(p0){} 48 bool operator ()(const point &aa,const point &bb){ 49 point a=aa,b=bb; 50 int k=(a-p)^(b-p); 51 if (k==0){ 52 return dis(a,p)-dis(b,p)<0; 53 } 54 return k>0; 55 } 56 }; 57 //极角排序 先找到左下角的点 58 //重载好point的'<' 59 void norm(){ 60 point mi=p[0]; 61 for (int i=1;i<n;i++) mi=min(mi,p[i]); 62 sort(p,p+n,cmp(mi)); 63 } 64 //得到凸包,点编号为0--n-1 65 void Graham(polygon &convex){ 66 norm(); 67 int &top=convex.n; 68 top=0; 69 if (n==1){ 70 top=1; convex.p[0]=p[0]; return ; 71 } 72 if (n==2){ 73 top=2; convex.p[0]=p[0]; convex.p[1]=p[1]; 74 if (convex.p[0]==convex.p[1]) top--; 75 return ; 76 } 77 convex.p[0]=p[0]; convex.p[1]=p[1]; top=2; 78 for (int i=2;i<n;i++){ 79 while (top>1 && ((convex.p[top-1]-convex.p[top-2])^(p[i]-convex.p[top-2]))<=0) top--; 80 convex.p[top++]=p[i]; 81 } 82 if (convex.n==2 && (convex.p[0]==convex.p[1])) convex.n--; 83 } 84 int getarea(){ 85 int sum=0; 86 for (int i=0;i<n;i++) sum+=(p[i]^(p[(i+1)%n])); 87 return sum/2; 88 } 89 }; 90 polygon C; 91 int main(){ 92 int n,x,y; cin >> n; C.n=0; 93 for (int i=0;i<n;i++){ 94 cin >> x >> y; 95 C.add(point(x,y)); 96 } 97 polygon ans; C.Graham(ans); 98 cout << ans.getarea()/50 << endl; 99 return 0; 100 }