2018 Multi-University Training Contest 3 - Problem G. Interstellar Travel (凸包)

2 篇文章 0 订阅

http://acm.hdu.edu.cn/showproblem.php?pid=6325

 

 

从凸包上面走会更优,所以答案的解肯定包括起点,终点,凸包拐点。

假如凸包一条边上有多点共线,那么就要看边上的点编号是否比边的终点编号小,是的话放到答案里解会更优。因为题目求的是字典序最小。

 

#include <stdio.h>
#include <iostream>
#include <string.h>
#include <algorithm>
using namespace std;
#define  LL long long
const int maxn = 200000+33;
struct point
{
    LL x,y;
    int id;
    bool friend operator < (point a,point b)
    {
        if(a.x!=b.x) return a.x<b.x;
        if(a.y!=b.y) return a.y>b.y;
        return a.id<b.id;
    }
}a[maxn];


point operator -(point A, point B) {
    point a;
    a.x=A.x-B.x;
    a.y=A.y-B.y;
    return a;
}
LL Cross(point A, point B) {return A.x*B.y-A.y*B.x;}

point top[maxn];
int n;
int G_tb()
{
    int m=0;
    for(int i=1;i<=n;i++){
        if(i!=1&&a[i].x==a[i-1].x) continue;
        while (m>1 && Cross(top[m]-top[m-1],a[i]-top[m-1]) > 0) m--;
        top[++m]=a[i];
    }

    return m;


}

int main()
{
    int T;
    scanf("%d",&T);
    while(T--){
        scanf("%d",&n);
        for(int i=1;i<=n;i++){
            scanf("%lld%lld",&a[i].x,&a[i].y);
            a[i].id=i;
        }
        sort(a+1,a+1+n);
        int m=G_tb();
        int vis[maxn],ans[maxn];
        memset(vis,0,sizeof vis);
        vis[1]=vis[m]=1;
        for(int i=2;i<m;i++){
            if(Cross(top[i]-top[i-1],top[i+1]-top[i-1])!=0)
                vis[i]=1;
        }
       ans[m]=top[m].id;
        for(int i=m-1;i>=1;i--){
            if(vis[i]) ans[i]=top[i].id;
            else{
                ans[i]=min(ans[i+1],top[i].id);
            }
        }
        for(int i=1;i<m;i++){
            if(ans[i]==top[i].id)
                printf("%d ",ans[i]);
        }
        printf("%d\n",n);


    }

    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值