Problem G. Interstellar Travel
Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 524288/524288 K (Java/Others)
Total Submission(s): 718 Accepted Submission(s): 158
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
做法:根据叉积的几何含义可知,走的路线和x轴围成的面积(x轴上面的面积减去下面的面积)的相反数就是代价,那么路线就是上凸包。
#include<bits/stdc++.h>
using namespace std;
const int N = 2e5+7;
struct node{
int x,y,ps;
bool operator<(const node &p)const{
if(x != p.x) return x < p.x;
if(y != p.y) return y > p.y;
return ps < p.ps;
}
};
node pt[N];
long long get(int x,int y,int z){
int ax = pt[y].x-pt[x].x;
int ay = pt[y].y-pt[x].y;
int bx = pt[z].x-pt[x].x;
int by = pt[z].y-pt[x].y;
return 1LL*ax*by-1LL*ay*bx;
}
int mn[N];
int que[N];
int main(){
int T;
cin >> T;
while(T--){
int n;
scanf("%d",&n);
for(int i = 1;i <= n;i ++) scanf("%d %d",&pt[i].x,&pt[i].y);
for(int i = 1;i <= n;i ++) pt[i].ps = i;
sort(pt+1,pt+n+1);
int now = 0;
que[0] = 1;
for(int i = 2;i <= n;i ++){
//cout << i << ' ' << pt[i].x << endl;
if(pt[i].x == pt[i-1].x) continue;
while(now && get(que[now-1],que[now],i)>0) now --;
que[++now] = i;
}
int l = 0,r;
printf("1");
while(l < now){
for(r = l+1;r <= now;r ++){
if(get(que[l],que[l+1],que[r])!= 0) break;
}
mn[r] = 1e9;
for(int i = r-1;i >= l;i --){
mn[i] = min(pt[que[i]].ps,mn[i+1]);
}
for(int i = l+1;i <= r-1;i ++)
if(mn[i] == pt[que[i]].ps) printf(" %d",pt[que[i]].ps);
l = r-1;
}
puts("");
}
return 0;
}