寻找凸包 | ||
---|---|---|
Time Limit: 1000 MS | Memory Limit: 1000 KB |
Description
给定平面上N个点, 请找出这N个点的凸包.
Input
第一行输入M表示包含M组测试数据,每组先输入N (N<=100), 接着输入N个坐标(x,y), x和y均为int型整数.
Output
以最下最左点开始逆时针输出凸包, 若有多个点在同一坐标,只输出一个,若凸包上有多个点在同一线上,只输出两端点.
Sample Input
2 7 1 1 4 1 4 4 4 4 1 4 2 2 5 5 8 5 6 8 3 1 8 5 7 3 5 3 5 1 8 2 11
Sample Output
case 1: 1 1 4 1 5 5 1 4 case 2: 8 3 2 11 1 8 3 5 示例代码: #include <stdio.h> #include <stdlib.h> #include <math.h> struct position_t { int x; int y; double angle; double len; } pos[2001], stack[2001]; int n; int top; int cmp_yx (const void * a, const void * b) { position_t *p1 = (position_t *)a; position_t *p2 = (position_t *)b; if(p1->y != p2->y) { return p1->y - p2->y; } else { return p1->x - p2->x; } } int cmp_angle (const void * a, const void * b) { position_t *p1 = (position_t *)a; position_t *p2 = (position_t *)b; if(p1->angle - p2->angle > 0) { return 1; } else if(p1->angle - p2->angle < 0) { return -1; } else { if(p1->len - p2->len > 0) { return 1; } else if(p1->len - p2->len < 0) { return -1; } else { return 0; } } } int push(int i) { stack[top].x = pos[i].x; stack[top].y = pos[i].y; stack[top].angle = pos[i].angle; top++; return top; } int initstack() { top = 0; } int pop() { top--; return top; } int isright(int a, int b, int x, int y) { if(a*y-b*x > 0) { return 0; } return 1; } int canpop(int i) { if(top<=2) { return 0; } if(isright(stack[top-1].x-stack[top-2].x, stack[top-1].y-stack[top-2].y, pos[i].x-stack[top-2].x, pos[i].y-stack[top-2].y)) { return 1; } return 0; } int isonline(int a, int b, int x, int y) { if(a*y-b*x ==0) { return 1; } return 0; } int findp0() { int minx = 2147483647; int miny = 2147483647; int idx = 0; for(int i=0; i<n; i++) { if(pos[i].y < miny) { miny = pos[i].y; idx = i; } } for(int i=0; i<n; i++) { if(pos[i].y==miny && pos[i].x<minx) { minx = pos[i].x; idx = i; } } return idx; } void sortangle() { for(int i=1; i<n; i++) { pos[i].len = sqrt((pos[i].y-pos[0].y)*(pos[i].y-pos[0].y)+(pos[i].x-pos[0].x)*(pos[i].x-pos[0].x)); pos[i].angle = acos((pos[i].x-pos[0].x)/pos[i].len); } qsort(&pos[1], n-1, sizeof(position_t), cmp_angle); } void removesame() { qsort(pos, n, sizeof(position_t), cmp_yx); int k=0; for(int i=1; i<n; i++) { if(pos[i].x==pos[k].x && pos[i].y==pos[k].y) { } else { k++; pos[k].x = pos[i].x; pos[k].y = pos[i].y; } } n = k+1; } int solve() { scanf("%d", &n); for(int i=0; i<n; i++) { scanf("%d%d", &pos[i].x, &pos[i].y); } removesame(); int idx = findp0(); position_t temppos = pos[idx]; for(int i=idx; i>0; i--) { pos[i] = pos[i-1]; } pos[0] = temppos; sortangle(); initstack(); push(0); int k = 2; for(; k<n; k++) { if(!isonline(pos[k].x-pos[0].x, pos[k].y-pos[0].y, pos[1].x-pos[0].x, pos[1].y-pos[0].y)) { break; } } push(k-1); push(k); for(int i=k+1; i<n; i++) { while(canpop(i)) { pop(); } push(i); } for(int i=0; i<top; i++) { printf("%d %d\n", stack[i].x, stack[i].y); } return 0; } int main() { int m; scanf("%d", &m); for(int i=0; i<m; i++) { printf("case %d:\n", i+1); solve(); } return 0; }