HDU 6325 Interstellar Travel 水平排序求凸包

Problem G. Interstellar Travel

Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 524288/524288 K (Java/Others)
Total Submission(s): 1776    Accepted Submission(s): 459


 

Problem Description

After trying hard for many years, Little Q has finally received an astronaut license. To celebrate the fact, he intends to buy himself a spaceship and make an interstellar travel.
Little Q knows the position of n planets in space, labeled by 1 to n . To his surprise, these planets are all coplanar. So to simplify, Little Q put these n planets on a plane coordinate system, and calculated the coordinate of each planet (xi,yi) .
Little Q plans to start his journey at the 1 -th planet, and end at the n -th planet. When he is at the i -th planet, he can next fly to the j -th planet only if xi<xj , which will cost his spaceship xi×yj−xj×yi units of energy. Note that this cost can be negative, it means the flight will supply his spaceship.
Please write a program to help Little Q find the best route with minimum total cost.

 

 

Input

The first line of the input contains an integer T(1≤T≤10) , denoting the number of test cases.
In each test case, there is an integer n(2≤n≤200000) in the first line, denoting the number of planets.
For the next n lines, each line contains 2 integers xi,yi(0≤xi,yi≤109) , denoting the coordinate of the i -th planet. Note that different planets may have the same coordinate because they are too close to each other. It is guaranteed that y1=yn=0,0=x1<x2,x3,...,xn−1<xn .

 

 

Output

For each test case, print a single line containing several distinct integers p1,p2,...,pm(1≤pi≤n) , denoting the route you chosen is p1→p2→...→pm−1→pm . Obviously p1 should be 1 and pm should be n . You should choose the route with minimum total cost. If there are multiple best routes, please choose the one with the smallest lexicographically.
A sequence of integers a is lexicographically smaller than a sequence of b if there exists such index j that ai=bi for all i<j , but aj<bj .

 

 

 

Sample Input

1

3

0 0

3 0

4 0

 

 

Sample Output

1 2 3

 

 

Source

2018 Multi-University Training Contest 3

 

 

题意:

     给你n个点,要你求走的点的顺序,这些点的横坐标必须严格递增,并且两两间的叉积要最小,如果有多个选择则输出字典序最小的。

 

做法:

     叉积最小很明显要顺时针走,那么我们要维护一个上凸包。又因为要求字典序最小,那么就不能用极角排序,因为极角排序不好处理共线的情况。注意:在开始选点之前需要筛一次点,把共点的情况给排除。


代码如下:

    

#include <bits/stdc++.h>
using namespace std;
struct Point{//点或向量

    double x, y;
    int id;
    Point() {}
    Point(double x, double y) :x(x), y(y) {}
};
typedef Point Vector;
double Cross(Vector a,Vector b){
    return a.x*b.y-a.y*b.x;
}
Vector operator - (Vector a, Vector b){
    return Vector(a.x-b.x,a.y-b.y);
}
int n, top;
Point P[600005], result[600005];
bool cmp(Point A, Point B){
    if(A.x==B.x&&A.y==B.y) return A.id<B.id;
    return A.x==B.x?A.y<B.y:A.x<B.x;
}
void Graham(){
    sort(P,P+n,cmp);
    int now=0;
    for(int i=1;i<n;i++)
        if(P[now].x!=P[i].x||P[now].y!=P[i].y)//筛点
            P[++now]=P[i];
    n=now+1;
    top=0;
    for (int i = 0; i < n; i++){
        while (top>1&&Cross(result[top-1]-result[top-2],P[i]-result[top-2])>0)
            top--;
        while(top>1&&Cross(result[top-1]-result[top-2],P[i]-result[top-2])==0&&result[top-1].id>P[i].id)
            top--;
        result[top++]=P[i];
    }
}
bool ccmp(Point A,Point B){
    return A.id<B.id;
}
int main(){
    int t;
    scanf("%d",&t);
    while(t--){
        scanf("%d",&n);
        scanf("%lf%lf",&P[0].x,&P[0].y);
        P[0].id=1;
        for(int i=n-1;i>=1;i--){
            scanf("%lf%lf",&P[i].x,&P[i].y);
            P[i].id=n-i+1;
        }
        Graham();
        for(int i=0;i<top;i++)
            printf("%d%c",result[i].id,i==top-1?'\n':' ');

    }
    return 0;
}

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值