题意:给出一组包括原点在内的点,求这组点凸包的各个顶点,并从原点按逆时针方向输出。
解法:graham算法, 栈保存点
graham算法:
内容:
找出左下方的点(这个店一定在凸包上),以这个点为极点,将所有点与这个点的极角排序。
依次加入新点得到新的边
如果和上一条边成左转关系就压栈继续 如果右转就弹栈直到和栈顶两点的边成左转关系 压栈继续
最后栈中的点即为凸包上的点。
具体详见:http://www.cnblogs.com/Booble/archive/2011/03/10/1980089.html#2065991
时间复杂度:O(n*log(n))->凸包算法的时间复杂度下限。
/*************************************************************************
> File Name: poj2007.cpp
> Author: cy
> Mail: 1002@qq.com
> Created Time: 2014/8/13 15:53:09
************************************************************************/
#include<iostream>
#include<cstring>
#include <algorithm>
#include<cstdlib>
#include<vector>
#include<cmath>
#include<stdlib.h>
#include<iomanip>
#include<list>
#include<deque>
#include<map>
#include <stdio.h>
#include <queue>
#define maxn 50+5
#define inf 0x3f3f3f3f
#define INF 0x3FFFFFFFFFFFFFFFLL
#define rep(i,n) for(i=0;i<n;i++)
#define reP(i,n) for(i=1;i<=n;i++)
#define ull unsigned long long
#define ll long long
#define cle(a) memset(a,0,sizeof(a))
using namespace std;
struct point{
double x,y;
};
point val[maxn];
int n;
int res[maxn];
int top;
bool cmp (point a,point b)
{
if(a.y==b.y)return a.x<b.x;
return a.y<b.y;
}
bool mult(point a,point b,point c)
{
return (a.x-c.x)*(b.y-c.y)>=(b.x-c.x)*(a.y-c.y);
}
void graham()
{
int i,len;
top=1;
sort(val,val+n,cmp);
if(n==0)return;res[0]=0;
if(n==1)return;res[1]=1;
if(n==2)return;res[2]=2;//
for(i=2;i<n;i++){
while(top&&mult(val[i],val[res[top]],val[res[top-1]]))top--;
res[++top]=i;
}
len=top;
res[++top]=n-2;
for(i=n-3;i>=0;i--){
while(top!=len&&mult(val[i],val[res[top]],val[res[top-1]]))top--;
res[++top]=i;
}
}
int main()
{
freopen("in.txt","r",stdin);
int i,j,k;
for(i=0;(cin>>val[i].x>>val[i].y);i++);
//cout<<i<<endl;
n=i;
graham();
int ip;//原点的位置
rep(ip,top)if(!val[res[ip]].x&&!val[res[ip]].y)break;
for(i=ip;i<top;i++)printf("(%.lf,%.lf)\n",val[res[i]].x,val[res[i]].y);
rep(i,ip)printf("(%.lf,%.lf)\n",val[res[i]].x,val[res[i]].y);
return 0;
}