圈水池(凸包入门)

 

圈水池

时间限制: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 }

 

posted @ 2015-11-02 13:57  handsomecui  阅读(405)  评论(0编辑  收藏  举报