圈水池
时间限制: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
1 #include <cstdio> 2 #include <algorithm> 3 #include <iostream> 4 5 using namespace std; 6 7 struct point 8 { 9 int x; 10 int y; 11 }p[105], s[105]; 12 13 bool cmp(point a, point b) 14 { 15 return a.x < b.x || (a.x == b.x && a.y < b.y); 16 } 17 18 /* 19 int dis(point a, point b) 20 { 21 return (a.x-b.x)*(a.x-b.x) + (a.y-b.y)*(a.y-b.y); 22 } 23 */ 24 25 bool judge(point a, point b, point c) 26 { 27 int abx = b.x-a.x; 28 int aby = b.y-a.y; 29 int acx = c.x-a.x; 30 int acy = c.y-a.y; 31 if(abx*acy - aby*acx > 0) // a、b、c成逆时针 32 return true; 33 return false; 34 } 35 36 int main() 37 { 38 int T, n, top, t; 39 scanf("%d", &T); 40 while(T--) 41 { 42 scanf("%d", &n); 43 for(int i = 0; i < n; ++i) 44 scanf("%d%d", &p[i].x, &p[i].y); 45 sort(p, p+n, cmp); 46 47 top = 0; 48 for(int i = 0; i < n; ++i) //求下凸包 49 { 50 while(top >= 2 && !judge(s[top-2], s[top-1], p[i])) 51 top--; 52 s[top++] = p[i]; 53 } 54 t = top-1; 55 for(int i = n-1; i >= 0; --i) // 求上凸包 56 { 57 while(top >= t+2 && !judge(s[top-2], s[top-1], p[i])) 58 top--; 59 s[top++] = p[i]; 60 } 61 --top; // 下凸包和上凸包的首尾点肯定是重叠的,所以删去 62 63 sort(s, s+top, cmp); 64 for(int i = 0; i < top; ++i) 65 printf("%d %d\n", s[i].x, s[i].y); 66 } 67 return 0; 68 }