Problem G. Interstellar TravelTime 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.
Input The first line of the input contains an integer T(1≤T≤10) , denoting the number of test cases.
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;
}