Uva - Convex Hull Finding - 凸包裸题 共线处理


A - Convex Hull Finding
Time Limit:3000MS     Memory Limit:0KB     64bit IO Format:%lld & %llu

Description

Download as PDF


  Convex Hull Finding 

Given a single connected contour, which is either convex or non-convex (concave), use any algorithm to find its Convex Hull, i.e., the smallest convex contour enclosing the given shape. If the given contour is convex, then its convex hull is the original contour itself. The maximal size of the shape is 512$\times$512, and the maximal number of the vertices of the shape is 512. Write a program to read the input data (the given shapes) from a disk file, implement your convex hull finding algorithm, and then output the shape data of the results to the standard output.

Input 

The order of the vertices is counterclockwise in  XY Cartesian Plane (if you consider the origin of the display window is on the upper-left corner, then the orientation of the vertices is clockwise), and none of the neighboring vertices are co-linear. Since all the shapes are closed contours, therefore, the last vertex should be identical to the first vertex. There are several sets of data within a given data file. The negative number  -1 is used to separate the data set.


LineData in 
Numberthe FileExplanation
1Ka positive integer showing how many sets of data in this file
2Na positive integer showing the number of vertices for the shape
3$X_1 \ Y_1$two positive integers for the first vertex (X1Y1)
4$X_2 \ Y_2$two positive integers for the next neighboring vertex (X2Y2)
...  
N+2$X_N \ Y_N$two positive integers for the last vertex (XNYN)
N+3-1Delimiter
N+4Ma positive integer showing the number of vertices for the next shape
N+5$XX_1 \ YY_1$two positive integers for the first vertex
...  


Note: Please note that the Line NumberData in the File and Explanation are not given in the file. They are shown here only to assist you in reading the data.

Output 

Output the convex hull of all  K input shapes to the standard output. The data format should be the same as the input file. In addition, the vertex with the smallest  Y value should be the first point and if there are points with the same  Y value, then the smallest  X value within those points should be the first point.

Sample Input 

3
15
30 30
50 60
60 20
70 45
86 39
112 60
200 113
250 50
300 200
130 240
76 150
47 76
36 40
33 35
30 30
-1
12
50 60
60 20
70 45
100 70
125 90
200 113
250 140
180 170
105 140
79 140
60 85
50 60
-1
6
60 20
250 140
180 170
79 140
50 60
60 20

Sample Output 

3
8
60 20
250 50
300 200
130 240
76 150
47 76
30 30
60 20
-1
6
60 20
250 140
180 170
79 140
50 60
60 20
-1
6
60 20
250 140
180 170
79 140
50 60
60 20




$\textstyle \parbox{.44\textwidth}{\begin{center}The contour shape of the firs......n in figure as follows:\mbox{}\epsfysize 2in \epsfbox{p681.eps}\end{center}}$$\textstyle \parbox{.44\textwidth}{\begin{center}The convex hull of the above ...... the following figure:\mbox{}\epsfysize 2in \epsfbox{p681b.eps}\end{center}}$



Miguel Revilla
2000-08-14


#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
struct pnode
{
  int x,y,len;
};
pnode point[600];

//找出凸包第一点 依题目 y值最小,y值相等的情况下x值小
bool cmpid(pnode a,pnode b)
{
    return a.y==b.y?a.x<b.x:a.y<b.y;
}

//计算两点的距离(平方
int dis(pnode a,pnode b)
{
    return (a.x-b.x)*(a.x-b.x) + (a.y-b.y)*(a.y-b.y);
}

//叉积
int crossproduct(pnode a,pnode b,pnode c)
{
    return (b.x-a.x)*(c.y-a.y)-(c.x-a.x)*(b.y-a.y);
}

//级角排序
bool cmpoint(pnode a,pnode b)
{
    int cp = crossproduct(point[0],a,b);
    if( cp==0 )
       return  a.len < b.len;//两点共线 则按距离小-》大排
    else
        return cp>0;
}

void output( int n )
{

    if(n<=2)
        puts("0");
    else
        {
            printf("%d\n",n);
            for( int i = 0;i<n;++i)
            printf("%d %d\n",point[i].x,point[i].y );
        }
}

void graham( int n)
{
    sort(point ,point+n,cmpid);

    int i;
    for( i = 1; i<n;++i)
        point[i].len = dis(point[0],point[i]);
    sort(point+1,point+n,cmpoint);

    //计算凸包
    int top = 1;
    for( i = 2;i<n;++i)
    {
        while( top>0 &&crossproduct(point[top-1],point[top],point[i])<=0 )
            --top;
        point[++top] = point[i];
    }
    point[++top] = point[0];

    //删除不是拐点的点
    int now = 1;
    for( i = 2; i<=top;++i)
    {
        if( crossproduct(point[now-1],point[now],point[i]) )
            point[++now] = point[i];
        else
            point[now] = point[i];
    }


    output(now+1);

}
int main()
{
   // freopen("in.txt","r",stdin);
    int cas;
    cin>>cas;
    printf("%d\n",cas);
    while(cas--)
    {
        int n;
        cin>>n;
        for( int i = 0;i <n;++i)
        {
            scanf("%d %d",&point[i].x,&point[i].y );
        }
        graham(n);
        int t;
        if( cas )
        {
             cin>>t;
             puts("-1");

        }


    }
    return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值