http://acm.nyist.net/JudgeOnline/problem.php?pid=78
圈水池
时间限制: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
分析:
凸包。
AC代码:
1 // NYOJ 78 -- 圈水池 Andrew 凸包算法 O(nlogn) 2 // 将凸包的顶点按 从小到大 先x后y的 顺序输出 3 // 4 /*test data 5 9 100 6 200 400 7 300 400 8 300 300 9 400 300 10 400 400 11 500 400 12 500 200 13 350 200 14 200 200 15 == 1628 16 17 */ 18 19 #include <cstdio> 20 #include <cmath> 21 #include <algorithm> 22 using namespace std; 23 24 const int MAXP = 1010; 25 const double Pzero = 0.00001; 26 27 struct POINT{ 28 int x,y; 29 }p[MAXP],CHp[MAXP*2]; 30 31 double XJ(POINT a, POINT b, POINT c){ 32 // vector a->b (b.x-a.x, b.y-a.y) 33 // vector a->c (c.x-a.x, c.y-a.y) 34 return (b.x-a.x)*(c.y-a.y) - (c.x-a.x)*(b.y-a.y); 35 } 36 37 bool comp(POINT a,POINT b){ 38 return (a.x < b.x) || ((a.x==b.x) && (a.y<b.y)); 39 } 40 41 int AndrewConvexHull(POINT *CHp, int n){ 42 // 计算凸包 CHp[] 逆时针存点 43 sort(p, p + n, comp); 44 int nCHp = 0; 45 for (int i = 0 ; i < n ; CHp[nCHp++] = p[i++]) 46 while(nCHp >= 2 && XJ(CHp[nCHp-2], CHp[nCHp-1], p[i]) <= 0) 47 nCHp--; 48 for (int i = n - 1,m = nCHp + 1 ; i >= 0 ; CHp[nCHp++] = p[i--]) 49 while(nCHp >= m && XJ(CHp[nCHp-2], CHp[nCHp-1], p[i]) <= 0) 50 nCHp--; 51 return --nCHp; 52 } 53 54 void init(int n){ 55 // 输入 56 for (int i = 0 ; i < n; i++) 57 scanf("%d%d", &p[i].x, &p[i].y); 58 } 59 60 void Output(int nCHp){ 61 sort(CHp, CHp + nCHp, comp); 62 for (int i = 0; i < nCHp ; i++){ 63 printf("%d %d ", CHp[i].x, CHp[i].y); 64 } 65 } 66 67 int main() 68 { 69 // freopen("in.txt","r",stdin); 70 int n;scanf("%d",&n); 71 while(~scanf("%d",&n) ){ 72 73 init(n); 74 int nCHp = AndrewConvexHull(CHp, n); 75 Output(nCHp); 76 } 77 return 0; 78 }