圈水池(凸包入门)
圈水池
时间限制:3000 ms | 内存限制:65535 KB
难度:4
- 描述
- 有一个牧场,牧场上有很多个供水装置,现在牧场的主人想要用篱笆把这些供水装置圈起来,以防止不是自己的牲畜来喝水,各个水池都标有各自的坐标,现在要你写一个程序利用最短的篱笆将这些供水装置圈起来!(篱笆足够多,并且长度可变)
- 输入
- 第一行输入的是N,代表用N组测试数据(1<=N<=10)
第二行输入的是m,代表本组测试数据共有m个供水装置(3<=m<=100)
接下来m行代表的是各个供水装置的横纵坐标 - 输出
- 输出各个篱笆经过各个供水装置的坐标点,并且按照x轴坐标值从小到大输出,如果x轴坐标值相同,再安照y轴坐标值从小到大输出
- 样例输入
-
1 4 0 0 1 1 2 3 3 0
- 样例输出
-
0 0 2 3 3 0
题解:用到了差积的特性,如果差积为负就是顺时针转,如果为正就是逆时针,如果为0就是共线;
代码:
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<cmath> 5 #include<algorithm> 6 using namespace std; 7 struct Node{ 8 int x,y; 9 friend int operator < (Node a,Node b){ 10 if(a.x<b.x||(a.x==b.x&&a.y<b.y))return 1; 11 else return 0; 12 } 13 }; 14 int chaji(Node a,Node b,Node c){ 15 return (b.x-a.x)*(c.y-a.y)-(b.y-a.y)*(c.x-a.x); 16 } 17 Node a[110],ans[110]; 18 int main(){ 19 int N,m; 20 scanf("%d",&N); 21 while(N--){ 22 scanf("%d",&m); 23 for(int i=0;i<m;i++)scanf("%d%d",&a[i].x,&a[i].y); 24 sort(a,a+m); 25 int k=0; 26 for(int i=0;i<m;i++){ 27 while(k>1&&chaji(ans[k-2],ans[k-1],a[i])<=0)k--; 28 ans[k++]=a[i]; 29 } 30 int t=k; 31 for(int i=m-1;i>=0;i--){ 32 while(k>t&&chaji(ans[k-2],ans[k-1],a[i])<=0)k--; 33 ans[k++]=a[i]; 34 } 35 k--; 36 sort(ans,ans+k); 37 for(int i=0;i<k;i++)printf("%d %d\n",ans[i].x,ans[i].y); 38 } 39 return 0; 40 }
另一种写法:
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<cmath> 5 #include<algorithm> 6 using namespace std; 7 struct Point{ 8 double x,y; 9 Point(double x=0,double y=0):x(x),y(y){} 10 }; 11 typedef Point Vector; 12 bool operator < (Vector a,Vector b){ 13 return a.x<b.x||(a.x==b.x&&a.y<b.y); 14 } 15 Vector operator - (Point a,Point b){return Vector(a.x-b.x,a.y-b.y);} 16 double Cross(Vector a,Vector b){ 17 return a.x*b.y-a.y*b.x; 18 } 19 Point a[110],ans[110]; 20 int main(){ 21 int N,m; 22 scanf("%d",&N); 23 while(N--){ 24 scanf("%d",&m); 25 for(int i=0;i<m;i++)scanf("%lf%lf",&a[i].x,&a[i].y); 26 sort(a,a+m); 27 int k=0; 28 for(int i=0;i<m;i++){ 29 while(k>1&&Cross(ans[k-1]-ans[k-2],a[i]-ans[k-2])<=0)k--; 30 ans[k++]=a[i]; 31 } 32 int t=k; 33 for(int i=m-1;i>=0;i--){ 34 while(k>t&&Cross(ans[k-1]-ans[k-2],a[i]-ans[k-2])<=0)k--; 35 ans[k++]=a[i]; 36 } 37 k--; 38 sort(ans,ans+k); 39 for(int i=0;i<k;i++)printf("%.0lf %.0lf\n",ans[i].x,ans[i].y); 40 } 41 return 0; 42 }