1.poj1113 Wall
题目:http://poj.org/problem?id=1113
题意:用一条线把若干个点包起来,并且线距离任何一个点的距离都不小于r。求这条线的最小距离是多少?
分析:这道题的答案是凸包周长加上一个圆周长,即包围凸包的一个圆角多边形,但是没弄明白那些圆角加起来为什么恰好是一个圆。每个圆角是以凸包对应的顶点为圆心,给定的L为半径,与相邻两条边的切点之间的一段圆弧。每个圆弧的两条半径夹角与对应的凸包的内角互补。假设凸包有n条边,则所有圆弧角之和为180°*n-180°*(n-2)=360°。故,围墙周长为=n条平行于凸包的线段+n条圆弧的长度=凸包周长+围墙离城堡距离L为半径的圆周长。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
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 ",(int)(res+0.5)); 114 return 0; 115 }
(为了套板子,写的很繁琐)
2.poj2007 Scrambled Polygon
题目:http://poj.org/problem?id=2007
题意:求一个凸多边形的凸包。要求起始点为输入的第一个点。
分析:rt。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
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) ",ans.p[(k+i)%ans.n].x,ans.p[(k+i)%ans.n].y); 96 } 97 return 0; 98 }
3.poj1228
题目:http://poj.org/problem?id=1228
题意:输入一个凸包上的点(没有凸包内部的点,要么是凸包顶点,要么是凸包边上的点),判断这个凸包是否稳定。所谓稳定就是判断能不能在原有凸包上加点。
分析:问凸包是否稳定。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include<iostream> 2 #include<cstring> 3 #include<algorithm> 4 #include<cmath> 5 using namespace std; 6 const double eps=1e-8; 7 const int maxn=1010; 8 int sgn(double x){ 9 if (fabs(x)<eps) return 0; 10 if (x<0) return -1; 11 return 1; 12 } 13 struct point{ 14 double x,y; 15 point(){} 16 point(double _x,double _y):x(_x),y(_y){} 17 point operator -(const point &b)const{ 18 return point(x-b.x,y-b.y); 19 } 20 double operator ^(const point &b)const{ 21 return x*b.y-y*b.x; 22 } 23 }p[maxn],pp[maxn]; 24 bool cmp(point a,point b) {return a.x < b.x || (a.x == b.x && a.y < b.y);} 25 int convexhull(point p[],int n,point pp[]){ 26 sort(p,p+n,cmp); 27 int m=0; 28 for (int i=0;i<n;i++){ 29 while (m>1 && ((pp[m-1]-pp[m-2])^(p[i]-pp[m-2]))<0) m--; 30 pp[m++]=p[i]; 31 } 32 int k=m; 33 for (int i=n-2;i>=0;i--){ 34 while (m>k && ((pp[m-1]-pp[m-2])^(p[i]-pp[m-2]))<0) m--; 35 pp[m++]=p[i]; 36 } 37 return m-1; 38 } 39 bool check(point p[],int n){ 40 for (int i=1;i<n-2;i++){ 41 if (((p[i-1]-p[i])^(p[i+1]-p[i]))!=0 && 42 ((p[i]-p[i+1])^(p[i+2]-p[i+1]))!=0) return false; //保证至少有三个点在同一条边上 43 } 44 return true; 45 } 46 int main(){ 47 int t,n; double x,y; cin >> t; 48 while (t--){ 49 cin >> n; 50 for (int i=0;i<n;i++) cin >> p[i].x >> p[i].y; 51 if (n<6){cout << "NO ";continue;} 52 int cnt=convexhull(p,n,pp); 53 if (check(pp,cnt)) cout << "YES "; else cout << "NO "; 54 } 55 return 0; 56 }
4
5.poj3348 Cows
题目:http://poj.org/problem?id=3348
题意:给出一些点圈出一个最大面积每50平方养一头牛问最多能养多少牛。
分析:凸包+多边形面积。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
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 }
6.poj1259/hdoj6219
题意:给出n个点,求出最大面积的凸包且凸包内不包含原点集中的点。
分析:rt。求最大面积空凸包。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include<iostream> 2 #include<cstring> 3 #include<algorithm> 4 #include<cmath> 5 using namespace std; 6 const double eps=1e-8; 7 const int maxn=1005; 8 inline double sqr(double x){return x*x;} 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 double x,y; 16 point(){} 17 point(double _x,double _y):x(_x),y(_y){} 18 //判断两点相同 19 bool operator ==(const point &b) const{ 20 return sgn(x-b.x)==0 && sgn(y-b.y)==0; 21 } 22 // 23 point operator -(const point &b) const{ 24 return point(x-b.x,y-b.y); 25 } 26 //叉积 27 double operator ^(const point &b) const{ 28 return x*b.y-y*b.x; 29 } 30 //点积 31 double operator *(const point &b) const{ 32 return x*b.x+y*b.y; 33 } 34 //重载小于号 (求最左下角的点 35 bool operator <(const point &b)const{ 36 return sgn(x-b.x)==0 ? sgn(y-b.y)<0 : x<b.x; 37 } 38 }p[maxn],pp[maxn]; 39 point tmp; 40 double dp[maxn][maxn]; 41 double empty_convex(point p[],int n,point o){ 42 double ans=0; 43 for (int i=0;i<n;i++) for (int j=0;j<n;j++) dp[i][j]=0; 44 for (int i=0;i<n;i++){ 45 int j=i-1; 46 while (j>=0 && ((p[i]-o)^(p[j]-o))==0) j--; 47 bool flag=(j==i-1); 48 while (j>=0){ 49 int k=j-1; 50 while (k>=0 && ((p[i]-p[k])^(p[j]-p[k]))>0) k--; 51 double area=fabs((p[i]-o)^(p[j]-o))/2.0; 52 if (k>=0) area+=dp[j][k]; 53 if (flag) dp[i][j]=area; 54 ans=max(ans,area); 55 j=k; 56 } 57 if (flag){ 58 for (int j=1;j<i;j++) dp[i][j]=max(dp[i][j],dp[i][j-1]); 59 } 60 } 61 return ans; 62 } 63 double dist(point a,point b){ 64 return sqrt((a-b)*(a-b)); 65 } 66 bool cmp_angle(point a,point b){ 67 double res=(a-tmp)^(b-tmp); 68 if (res) return res>0; 69 return dist(a,tmp)<dist(b,tmp); 70 } 71 double largest_empty_convex(point p[],int n){ 72 double ans=0; 73 for (int i=0;i<n;i++){ 74 tmp=p[i]; 75 int cnt=0; 76 for (int j=0;j<n;j++){ 77 if (p[j].y>tmp.y || p[j].y==tmp.y && p[j].x>tmp.x) pp[cnt++]=p[j]; 78 } 79 sort(pp,pp+cnt,cmp_angle); //根据极角排序 80 ans=max(ans,empty_convex(pp,cnt,tmp)); 81 } 82 return ans; 83 } 84 int main(){ 85 int t,n; cin >> t; 86 while (t--){ 87 cin >> n; 88 for (int i=0;i<n;i++) cin >> p[i].x >> p[i].y; 89 double ans=largest_empty_convex(p,n); 90 printf("%.1f ",ans); 91 } 92 return 0; 93 }