hdu6325 Interstellar Travel 凸包变形

题目传送门

题目大意:

       给出n个平面坐标,保证第一个点和第n个点y值为0,其余点的x坐标都在中间,要从 i 点走到 j 点的要求是 i 点的横坐标严格小于 j 的横坐标,并且消耗的能量是(x* y- x* yi),要求消耗的能量最小(能量可以为负),并且字典序要求最小。

思路:

      消耗能量的式子就是两个坐标的叉积,叉积的几何意义就是两个向量对应的平行四边形的面积,但是这个面积会有正负,如果向量 j 在向量 i 的顺时针方向,则这个面积是负的,如果我希望能量最小,那么就尽可能使向量是顺时针方向的,由此发现其实就得到了一个凸包,而且是一个上凸包。经过凸包上的点都符合能量的要求,但是由于要求字典序最小,所以如果凸包上的某一条边上有很多点,那么就需要判断一下这些点的id,如果线段中间的点的id比较小,那么这些点选上了之后,字典序肯定会变小,所以在做凸包的时候就要对凸包算法加一点点变形。

#include<cstdio>
#include<algorithm>
#include<iostream>
#include<vector>
#include<map>
#include<set>
#include<cstring>
#include<queue>
#include<stack>
#define CLR(a,b) memset(a,b,sizeof(a))
#define mkp(a,b) make_pair(a,b)
typedef long long ll;
using namespace std;
const int inf = 0x3f3f3f3f;
const int maxn = 200010;
struct dian {
    double x, y;
    int id;
    dian (){}
    dian(double x, double y, int id) :x(x), y(y), id(id){}
}a[maxn],ch[maxn];
bool cmp(dian &a, dian &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;
}
typedef dian Vector;
Vector operator -(Vector a, Vector b) {
    return Vector ( a.x - b.x, a.y - b.y,0 );
}
bool operator == (Vector a,Vector b){
    return ((a.x==b.x) && (a.y==b.y));
}
double cross(Vector a, Vector b)
{
    return a.x*b.y - a.y*b.x;
}
int andrew(dian *p, int n, dian *ch)
{
    int m = 0;
    sort(p, p + n, cmp);
    for (int i = 0; i < n; i++)
    {
        if(i>0&&p[i]==ch[m-1])continue;
        while (m > 1 && cross(ch[m - 2] - ch[m - 1], p[i] - ch[m - 1] )<= 0)
        {
            if(cross(ch[m - 2] - ch[m - 1], p[i] - ch[m - 1] )< 0)
            m--;
            else if(ch[m-1].id>p[i].id){
                m--;
            }else break;
        }
        ch[m++] = p[i];
    }
    return m;
}    
bool vis[maxn];
int main() {
    int n,T;
    cin >> T;
    while (T--)
    {
        CLR(vis, inf);
        scanf("%d", &n);
        for (int i = 0; i < n; i++)
        {
            scanf("%lf%lf", &a[i].x, &a[i].y);
            a[i].id = i+1;
        }
        int m = andrew(a, n, ch);
        for (int i = 0; i<=m-1; i++)
        {
            printf("%d", ch[i].id);
            if (i < m-1)printf(" ");
            else printf("\n");
        }
    }
    

}

/*

1
7
0 0
9 0
3 6
1 2
3 6
2 4
10 0


*/

Problem G. Interstellar Travel

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


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×yjxj×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(1T10), denoting the number of test cases.
In each test case, there is an integer n(2n200000) in the first line, denoting the number of planets.
For the next n lines, each line contains 2 integers xi,yi(0xi,yi109), 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,...,xn1<xn.
 

 

Output
For each test case, print a single line containing several distinct integers p1,p2,...,pm(1pin), denoting the route you chosen is p1p2...pm1pm. 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
posted @ 2018-09-05 12:14  光芒万丈小太阳  阅读(626)  评论(0编辑  收藏  举报