poj 1696 Space Ant

很好的题。。可以来检验一发graham算法求凸包是否掌握了,其实这个题没有最外侧的点与x轴,或者与y轴平行的数据,不然的话还要修改一个部分~~

可以试试这组数据

1

8

1 1 1

2 2 1

3 1 2

4 2 2

5 1 3

6 2 3

7 1 4

8 2 4

正确的答案应该输出的是8 1 2 4 6 8 7 5 3

但是输出的是8 1 2 8 7 3 4 6 5也能AC,这就是求凸包的时候判断是否有等于了~~~~~

#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<algorithm>
const double EPS=1e-10;
const double pi=acos(-1.0);
using namespace std;
double add(double a,double b){
    if(abs(a+b)<=EPS*(abs(a)*abs(b)))
		return 0;
    return a+b;
}
struct P
{
    double x,y;
    int index;
    P(){}
    P (double x,double y):x(x),y(y){
    }
    P operator +(P p){
        return P(add(x,p.x),add(y,p.y));
    }
    P operator -(P p){
        return P(add(x,-p.x),add(y,-p.y));
    }
    P operator *(double d){
        return P(x*d,y*d);
    }
    double det(P p){
        return add(x*p.y,-y*p.x);
    }
    double dot(P p){
        return add(x*p.x,y*p.y);
    }
};
bool cmp(P a,P b)
{
    if(a.x!=b.x)
		return a.x<b.x;
    return a.y<b.y;
}
P p[100000],q[100000];
int vis[100000];
int ans[100000];
P ps[1000000];
int main()
{
    int T,n,l;
    scanf("%d",&T);
    while(T--)
    {
		memset(vis,0,sizeof(vis));
        int k=0;
        scanf("%d",&n);
        int mink=0;
        double mn=10000000.0;
        for(int i=0;i<n;i++)
        {
            scanf("%d%lf%lf",&p[i].index,&p[i].x,&p[i].y);
            if(mn>p[i].y)
            {
                mn=p[i].y;
                mink=p[i].index;
            }
        }
        sort(p,p+n,cmp);
        for(int i=0;i<n;i++)
        {
            if(p[i].index==mink)
            {
                mink=i;
                break;
            }
        }
        int first=1;
        int l=k;
        while(1)
        {
			for(int i=mink,t=k;i<n;i++)
			{
				if(vis[p[i].index])
					continue;
					if(t==0)   //当凸包里什么都没有时,需要先放两个点进去;如果有点则不管,因为都要满足不能右转
					{
					    while(k>1 && (ps[k-1]-ps[k-2]).det(p[i]-ps[k-2])<0) k--;
                        ps[k++]=p[i];
					}
					else
					{
                        while(k>t && (ps[k-1]-ps[k-2]).det(p[i]-ps[k-2])<0) k--;
                        ps[k++]=p[i];
					}
			}
			for(int i=0;i<k;i++)
				vis[ps[i].index]=1;
			for(int i=n-2,t=k;i>=0;i--)
			{
				if(vis[p[i].index])
					continue;
				while(k>t && (ps[k-1]-ps[k-2]).det(p[i]-ps[k-2])<0) k--;
				ps[k++]=p[i];
			}
			for(int i=0;i<k;i++)
				vis[ps[i].index]=1;
            if(l==k)
				break;
            l=k;
            mink=0;
        }
		printf("%d",n);
		for(int i=0;i<k;i++)
			printf(" %d",ps[i].index);
		printf("\n");
	}
	return 0;
}


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值