题目链接:http://acm.nyist.net/JudgeOnline/problem.php?pid=78
题目分析:
这道题其实就是给若干的点,然后求这些点的凸包,最后将这些点的凸包按x坐标从小到大的顺序输出,如果x坐标相同,就按y坐标从小到大输出。
至于求凸包的步骤,要是没有图的话,很难描述。如果有叉乘的概念的话,看代码应该就可以理解一点。有时间的时候再把图贴上细讲吧。下面给出大概的步骤。
1、首先要在给出的点列中,找到最左下角的点,作为基准点。
2、将其他剩余的点,以找到的左下角的点为基准点,进行逆时针排序,最后将基准点加进去,因为基准点既是始点,也是终点。
3、对排序后的点求凸包。
4、对求得的凸包,按要求输出。
对照着代码和实现步骤,将就看吧~
参考代码:
#include<stdio.h>
#include<stdlib.h>
const int N = 105;
typedef struct
{
int x;
int y;
}POINT;
POINT point[N];
POINT stack[N];
inline int CrossProduct(const POINT *a, const POINT *b, const POINT *c)
{//计算向量(b-a)×(b-c)
return (a->x - b->x) * (b->y - c->y) - (b->x - c->x) * (a->y - b->y);
}
//将每个点按照向量(point[0] - point[i])顺时针排列
int compare1(const void *a, const void *b)
{
POINT *p1 = (POINT *)a;
POINT *p2 = (POINT *)b;
return CrossProduct(&point[0], p1, p2);
}
int compare2(const void *a, const void *b)
{
POINT *p1 = (POINT *)a;
POINT *p2 = (POINT *)b;
if(p1->x == p2->x)
return p1->y - p2->y;
else
return p1->x - p2->x;
}
int Convex(int n)
{
int top = 2;
stack[0] = point[0];
stack[1] = point[1];
stack[2] = point[2];
for(int i = 3; i < n; ++i)
{
while(CrossProduct(&stack[top - 1], &stack[top], &point[i]) >= 0)
--top;
stack[++top] = point[i];
}
return top;
}
int main()
{
int t,n;
int i,Index;
POINT temp;
scanf("%d", &t);
while(t--)
{
scanf("%d",&n);
for(i = 0; i < n; ++i)
scanf("%d %d",&point[i].x, &point[i].y);
//找到左下角的点,放在point[0]里面。
Index = 0;
for(i = 1; i < n; ++i)
{
if(point[i].x <= point[Index].x && point[i].y <= point[Index].y)
Index = i;
}
temp = point[0];
point[0] = point[Index];
point[Index] = temp;
//将所有点按顺时针排序
qsort(&point[1], n - 1, sizeof(point[0]),compare1);
//最后加入point[0];
point[n] = point[0];
++n;
Index = Convex(n);
qsort(stack, Index, sizeof(stack[0]), compare2);//最后对得到的凸包中的点进行排序
for(i = 0; i < Index; ++i)
printf("%d %d\n",stack[i].x, stack[i].y);
}
return 0;
}